/Objects/structseq.c

http://unladen-swallow.googlecode.com/ · C · 539 lines · 460 code · 68 blank · 11 comment · 78 complexity · 87a37fbb71cd4f4dbe8993efa84c8f91 MD5 · raw file

  1. /* Implementation helper: a struct that looks like a tuple. See timemodule
  2. and posixmodule for example uses. */
  3. #include "Python.h"
  4. #include "structmember.h"
  5. #include "structseq.h"
  6. static char visible_length_key[] = "n_sequence_fields";
  7. static char real_length_key[] = "n_fields";
  8. static char unnamed_fields_key[] = "n_unnamed_fields";
  9. /* Fields with this name have only a field index, not a field name.
  10. They are only allowed for indices < n_visible_fields. */
  11. char *PyStructSequence_UnnamedField = "unnamed field";
  12. #define VISIBLE_SIZE(op) Py_SIZE(op)
  13. #define VISIBLE_SIZE_TP(tp) PyInt_AsLong( \
  14. PyDict_GetItemString((tp)->tp_dict, visible_length_key))
  15. #define REAL_SIZE_TP(tp) PyInt_AsLong( \
  16. PyDict_GetItemString((tp)->tp_dict, real_length_key))
  17. #define REAL_SIZE(op) REAL_SIZE_TP(Py_TYPE(op))
  18. #define UNNAMED_FIELDS_TP(tp) PyInt_AsLong( \
  19. PyDict_GetItemString((tp)->tp_dict, unnamed_fields_key))
  20. #define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP(Py_TYPE(op))
  21. PyObject *
  22. PyStructSequence_New(PyTypeObject *type)
  23. {
  24. PyStructSequence *obj;
  25. obj = PyObject_New(PyStructSequence, type);
  26. if (obj == NULL)
  27. return NULL;
  28. Py_SIZE(obj) = VISIBLE_SIZE_TP(type);
  29. return (PyObject*) obj;
  30. }
  31. static void
  32. structseq_dealloc(PyStructSequence *obj)
  33. {
  34. Py_ssize_t i, size;
  35. size = REAL_SIZE(obj);
  36. for (i = 0; i < size; ++i) {
  37. Py_XDECREF(obj->ob_item[i]);
  38. }
  39. PyObject_Del(obj);
  40. }
  41. static Py_ssize_t
  42. structseq_length(PyStructSequence *obj)
  43. {
  44. return VISIBLE_SIZE(obj);
  45. }
  46. static PyObject*
  47. structseq_item(PyStructSequence *obj, Py_ssize_t i)
  48. {
  49. if (i < 0 || i >= VISIBLE_SIZE(obj)) {
  50. PyErr_SetString(PyExc_IndexError, "tuple index out of range");
  51. return NULL;
  52. }
  53. Py_INCREF(obj->ob_item[i]);
  54. return obj->ob_item[i];
  55. }
  56. static PyObject*
  57. structseq_slice(PyStructSequence *obj, Py_ssize_t low, Py_ssize_t high)
  58. {
  59. PyTupleObject *np;
  60. Py_ssize_t i;
  61. if (low < 0)
  62. low = 0;
  63. if (high > VISIBLE_SIZE(obj))
  64. high = VISIBLE_SIZE(obj);
  65. if (high < low)
  66. high = low;
  67. np = (PyTupleObject *)PyTuple_New(high-low);
  68. if (np == NULL)
  69. return NULL;
  70. for(i = low; i < high; ++i) {
  71. PyObject *v = obj->ob_item[i];
  72. Py_INCREF(v);
  73. PyTuple_SET_ITEM(np, i-low, v);
  74. }
  75. return (PyObject *) np;
  76. }
  77. static PyObject *
  78. structseq_subscript(PyStructSequence *self, PyObject *item)
  79. {
  80. if (PyIndex_Check(item)) {
  81. Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
  82. if (i == -1 && PyErr_Occurred())
  83. return NULL;
  84. if (i < 0)
  85. i += VISIBLE_SIZE(self);
  86. if (i < 0 || i >= VISIBLE_SIZE(self)) {
  87. PyErr_SetString(PyExc_IndexError,
  88. "tuple index out of range");
  89. return NULL;
  90. }
  91. Py_INCREF(self->ob_item[i]);
  92. return self->ob_item[i];
  93. }
  94. else if (PySlice_Check(item)) {
  95. Py_ssize_t start, stop, step, slicelen, cur, i;
  96. PyObject *result;
  97. if (PySlice_GetIndicesEx((PySliceObject *)item,
  98. VISIBLE_SIZE(self), &start, &stop,
  99. &step, &slicelen) < 0) {
  100. return NULL;
  101. }
  102. if (slicelen <= 0)
  103. return PyTuple_New(0);
  104. result = PyTuple_New(slicelen);
  105. if (result == NULL)
  106. return NULL;
  107. for (cur = start, i = 0; i < slicelen;
  108. cur += step, i++) {
  109. PyObject *v = self->ob_item[cur];
  110. Py_INCREF(v);
  111. PyTuple_SET_ITEM(result, i, v);
  112. }
  113. return result;
  114. }
  115. else {
  116. PyErr_SetString(PyExc_TypeError,
  117. "structseq index must be integer");
  118. return NULL;
  119. }
  120. }
  121. static PyObject *
  122. structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  123. {
  124. PyObject *arg = NULL;
  125. PyObject *dict = NULL;
  126. PyObject *ob;
  127. PyStructSequence *res = NULL;
  128. Py_ssize_t len, min_len, max_len, i, n_unnamed_fields;
  129. static char *kwlist[] = {"sequence", "dict", 0};
  130. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:structseq",
  131. kwlist, &arg, &dict))
  132. return NULL;
  133. arg = PySequence_Fast(arg, "constructor requires a sequence");
  134. if (!arg) {
  135. return NULL;
  136. }
  137. if (dict && !PyDict_Check(dict)) {
  138. PyErr_Format(PyExc_TypeError,
  139. "%.500s() takes a dict as second arg, if any",
  140. type->tp_name);
  141. Py_DECREF(arg);
  142. return NULL;
  143. }
  144. len = PySequence_Fast_GET_SIZE(arg);
  145. min_len = VISIBLE_SIZE_TP(type);
  146. max_len = REAL_SIZE_TP(type);
  147. n_unnamed_fields = UNNAMED_FIELDS_TP(type);
  148. if (min_len != max_len) {
  149. if (len < min_len) {
  150. PyErr_Format(PyExc_TypeError,
  151. "%.500s() takes an at least %zd-sequence (%zd-sequence given)",
  152. type->tp_name, min_len, len);
  153. Py_DECREF(arg);
  154. return NULL;
  155. }
  156. if (len > max_len) {
  157. PyErr_Format(PyExc_TypeError,
  158. "%.500s() takes an at most %zd-sequence (%zd-sequence given)",
  159. type->tp_name, max_len, len);
  160. Py_DECREF(arg);
  161. return NULL;
  162. }
  163. }
  164. else {
  165. if (len != min_len) {
  166. PyErr_Format(PyExc_TypeError,
  167. "%.500s() takes a %zd-sequence (%zd-sequence given)",
  168. type->tp_name, min_len, len);
  169. Py_DECREF(arg);
  170. return NULL;
  171. }
  172. }
  173. res = (PyStructSequence*) PyStructSequence_New(type);
  174. if (res == NULL) {
  175. return NULL;
  176. }
  177. for (i = 0; i < len; ++i) {
  178. PyObject *v = PySequence_Fast_GET_ITEM(arg, i);
  179. Py_INCREF(v);
  180. res->ob_item[i] = v;
  181. }
  182. for (; i < max_len; ++i) {
  183. if (dict && (ob = PyDict_GetItemString(
  184. dict, type->tp_members[i-n_unnamed_fields].name))) {
  185. }
  186. else {
  187. ob = Py_None;
  188. }
  189. Py_INCREF(ob);
  190. res->ob_item[i] = ob;
  191. }
  192. Py_DECREF(arg);
  193. return (PyObject*) res;
  194. }
  195. static PyObject *
  196. make_tuple(PyStructSequence *obj)
  197. {
  198. return structseq_slice(obj, 0, VISIBLE_SIZE(obj));
  199. }
  200. static PyObject *
  201. structseq_repr(PyStructSequence *obj)
  202. {
  203. /* buffer and type size were chosen well considered. */
  204. #define REPR_BUFFER_SIZE 512
  205. #define TYPE_MAXSIZE 100
  206. PyObject *tup;
  207. PyTypeObject *typ = Py_TYPE(obj);
  208. int i, removelast = 0;
  209. Py_ssize_t len;
  210. char buf[REPR_BUFFER_SIZE];
  211. char *endofbuf, *pbuf = buf;
  212. /* pointer to end of writeable buffer; safes space for "...)\0" */
  213. endofbuf= &buf[REPR_BUFFER_SIZE-5];
  214. if ((tup = make_tuple(obj)) == NULL) {
  215. return NULL;
  216. }
  217. /* "typename(", limited to TYPE_MAXSIZE */
  218. len = strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE :
  219. strlen(typ->tp_name);
  220. strncpy(pbuf, typ->tp_name, len);
  221. pbuf += len;
  222. *pbuf++ = '(';
  223. for (i=0; i < VISIBLE_SIZE(obj); i++) {
  224. PyObject *val, *repr;
  225. char *cname, *crepr;
  226. cname = typ->tp_members[i].name;
  227. val = PyTuple_GetItem(tup, i);
  228. if (cname == NULL || val == NULL) {
  229. return NULL;
  230. }
  231. repr = PyObject_Repr(val);
  232. if (repr == NULL) {
  233. Py_DECREF(tup);
  234. return NULL;
  235. }
  236. crepr = PyString_AsString(repr);
  237. if (crepr == NULL) {
  238. Py_DECREF(tup);
  239. Py_DECREF(repr);
  240. return NULL;
  241. }
  242. /* + 3: keep space for "=" and ", " */
  243. len = strlen(cname) + strlen(crepr) + 3;
  244. if ((pbuf+len) <= endofbuf) {
  245. strcpy(pbuf, cname);
  246. pbuf += strlen(cname);
  247. *pbuf++ = '=';
  248. strcpy(pbuf, crepr);
  249. pbuf += strlen(crepr);
  250. *pbuf++ = ',';
  251. *pbuf++ = ' ';
  252. removelast = 1;
  253. Py_DECREF(repr);
  254. }
  255. else {
  256. strcpy(pbuf, "...");
  257. pbuf += 3;
  258. removelast = 0;
  259. Py_DECREF(repr);
  260. break;
  261. }
  262. }
  263. Py_DECREF(tup);
  264. if (removelast) {
  265. /* overwrite last ", " */
  266. pbuf-=2;
  267. }
  268. *pbuf++ = ')';
  269. *pbuf = '\0';
  270. return PyString_FromString(buf);
  271. }
  272. static PyObject *
  273. structseq_concat(PyStructSequence *obj, PyObject *b)
  274. {
  275. PyObject *tup, *result;
  276. tup = make_tuple(obj);
  277. result = PySequence_Concat(tup, b);
  278. Py_DECREF(tup);
  279. return result;
  280. }
  281. static PyObject *
  282. structseq_repeat(PyStructSequence *obj, Py_ssize_t n)
  283. {
  284. PyObject *tup, *result;
  285. tup = make_tuple(obj);
  286. result = PySequence_Repeat(tup, n);
  287. Py_DECREF(tup);
  288. return result;
  289. }
  290. static int
  291. structseq_contains(PyStructSequence *obj, PyObject *o)
  292. {
  293. PyObject *tup;
  294. int result;
  295. tup = make_tuple(obj);
  296. if (!tup)
  297. return -1;
  298. result = PySequence_Contains(tup, o);
  299. Py_DECREF(tup);
  300. return result;
  301. }
  302. static long
  303. structseq_hash(PyObject *obj)
  304. {
  305. PyObject *tup;
  306. long result;
  307. tup = make_tuple((PyStructSequence*) obj);
  308. if (!tup)
  309. return -1;
  310. result = PyObject_Hash(tup);
  311. Py_DECREF(tup);
  312. return result;
  313. }
  314. static PyObject *
  315. structseq_richcompare(PyObject *obj, PyObject *o2, int op)
  316. {
  317. PyObject *tup, *result;
  318. tup = make_tuple((PyStructSequence*) obj);
  319. result = PyObject_RichCompare(tup, o2, op);
  320. Py_DECREF(tup);
  321. return result;
  322. }
  323. static PyObject *
  324. structseq_reduce(PyStructSequence* self)
  325. {
  326. PyObject* tup;
  327. PyObject* dict;
  328. PyObject* result;
  329. Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields;
  330. int i;
  331. n_fields = REAL_SIZE(self);
  332. n_visible_fields = VISIBLE_SIZE(self);
  333. n_unnamed_fields = UNNAMED_FIELDS(self);
  334. tup = PyTuple_New(n_visible_fields);
  335. if (!tup) {
  336. return NULL;
  337. }
  338. dict = PyDict_New();
  339. if (!dict) {
  340. Py_DECREF(tup);
  341. return NULL;
  342. }
  343. for (i = 0; i < n_visible_fields; i++) {
  344. Py_INCREF(self->ob_item[i]);
  345. PyTuple_SET_ITEM(tup, i, self->ob_item[i]);
  346. }
  347. for (; i < n_fields; i++) {
  348. char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;
  349. PyDict_SetItemString(dict, n,
  350. self->ob_item[i]);
  351. }
  352. result = Py_BuildValue("(O(OO))", Py_TYPE(self), tup, dict);
  353. Py_DECREF(tup);
  354. Py_DECREF(dict);
  355. return result;
  356. }
  357. static PySequenceMethods structseq_as_sequence = {
  358. (lenfunc)structseq_length,
  359. (binaryfunc)structseq_concat, /* sq_concat */
  360. (ssizeargfunc)structseq_repeat, /* sq_repeat */
  361. (ssizeargfunc)structseq_item, /* sq_item */
  362. (ssizessizeargfunc)structseq_slice, /* sq_slice */
  363. 0, /* sq_ass_item */
  364. 0, /* sq_ass_slice */
  365. (objobjproc)structseq_contains, /* sq_contains */
  366. };
  367. static PyMappingMethods structseq_as_mapping = {
  368. (lenfunc)structseq_length,
  369. (binaryfunc)structseq_subscript,
  370. };
  371. static PyMethodDef structseq_methods[] = {
  372. {"__reduce__", (PyCFunction)structseq_reduce,
  373. METH_NOARGS, NULL},
  374. {NULL, NULL}
  375. };
  376. static PyTypeObject _struct_sequence_template = {
  377. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  378. NULL, /* tp_name */
  379. 0, /* tp_basicsize */
  380. 0, /* tp_itemsize */
  381. (destructor)structseq_dealloc, /* tp_dealloc */
  382. 0, /* tp_print */
  383. 0, /* tp_getattr */
  384. 0, /* tp_setattr */
  385. 0, /* tp_compare */
  386. (reprfunc)structseq_repr, /* tp_repr */
  387. 0, /* tp_as_number */
  388. &structseq_as_sequence, /* tp_as_sequence */
  389. &structseq_as_mapping, /* tp_as_mapping */
  390. structseq_hash, /* tp_hash */
  391. 0, /* tp_call */
  392. 0, /* tp_str */
  393. 0, /* tp_getattro */
  394. 0, /* tp_setattro */
  395. 0, /* tp_as_buffer */
  396. Py_TPFLAGS_DEFAULT, /* tp_flags */
  397. NULL, /* tp_doc */
  398. 0, /* tp_traverse */
  399. 0, /* tp_clear */
  400. structseq_richcompare, /* tp_richcompare */
  401. 0, /* tp_weaklistoffset */
  402. 0, /* tp_iter */
  403. 0, /* tp_iternext */
  404. structseq_methods, /* tp_methods */
  405. NULL, /* tp_members */
  406. 0, /* tp_getset */
  407. 0, /* tp_base */
  408. 0, /* tp_dict */
  409. 0, /* tp_descr_get */
  410. 0, /* tp_descr_set */
  411. 0, /* tp_dictoffset */
  412. 0, /* tp_init */
  413. 0, /* tp_alloc */
  414. structseq_new, /* tp_new */
  415. };
  416. void
  417. PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
  418. {
  419. PyObject *dict;
  420. PyMemberDef* members;
  421. int n_members, n_unnamed_members, i, k;
  422. #ifdef Py_TRACE_REFS
  423. /* if the type object was chained, unchain it first
  424. before overwriting its storage */
  425. if (type->_ob_next) {
  426. _Py_ForgetReference((PyObject*)type);
  427. }
  428. #endif
  429. n_unnamed_members = 0;
  430. for (i = 0; desc->fields[i].name != NULL; ++i)
  431. if (desc->fields[i].name == PyStructSequence_UnnamedField)
  432. n_unnamed_members++;
  433. n_members = i;
  434. memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject));
  435. type->tp_name = desc->name;
  436. type->tp_doc = desc->doc;
  437. type->tp_basicsize = sizeof(PyStructSequence)+
  438. sizeof(PyObject*)*(n_members-1);
  439. type->tp_itemsize = 0;
  440. members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1);
  441. if (members == NULL)
  442. return;
  443. for (i = k = 0; i < n_members; ++i) {
  444. if (desc->fields[i].name == PyStructSequence_UnnamedField)
  445. continue;
  446. members[k].name = desc->fields[i].name;
  447. members[k].type = T_OBJECT;
  448. members[k].offset = offsetof(PyStructSequence, ob_item)
  449. + i * sizeof(PyObject*);
  450. members[k].flags = READONLY;
  451. members[k].doc = desc->fields[i].doc;
  452. k++;
  453. }
  454. members[k].name = NULL;
  455. type->tp_members = members;
  456. if (PyType_Ready(type) < 0)
  457. return;
  458. Py_INCREF(type);
  459. dict = type->tp_dict;
  460. #define SET_DICT_FROM_INT(key, value) \
  461. do { \
  462. PyObject *v = PyInt_FromLong((long) value); \
  463. if (v != NULL) { \
  464. PyDict_SetItemString(dict, key, v); \
  465. Py_DECREF(v); \
  466. } \
  467. } while (0)
  468. SET_DICT_FROM_INT(visible_length_key, desc->n_in_sequence);
  469. SET_DICT_FROM_INT(real_length_key, n_members);
  470. SET_DICT_FROM_INT(unnamed_fields_key, n_unnamed_members);
  471. }