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.

540 lines
16 KiB

14 years ago
14 years ago
14 years ago
  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. Py_DECREF(arg);
  176. return NULL;
  177. }
  178. for (i = 0; i < len; ++i) {
  179. PyObject *v = PySequence_Fast_GET_ITEM(arg, i);
  180. Py_INCREF(v);
  181. res->ob_item[i] = v;
  182. }
  183. for (; i < max_len; ++i) {
  184. if (dict && (ob = PyDict_GetItemString(
  185. dict, type->tp_members[i-n_unnamed_fields].name))) {
  186. }
  187. else {
  188. ob = Py_None;
  189. }
  190. Py_INCREF(ob);
  191. res->ob_item[i] = ob;
  192. }
  193. Py_DECREF(arg);
  194. return (PyObject*) res;
  195. }
  196. static PyObject *
  197. make_tuple(PyStructSequence *obj)
  198. {
  199. return structseq_slice(obj, 0, VISIBLE_SIZE(obj));
  200. }
  201. static PyObject *
  202. structseq_repr(PyStructSequence *obj)
  203. {
  204. /* buffer and type size were chosen well considered. */
  205. #define REPR_BUFFER_SIZE 512
  206. #define TYPE_MAXSIZE 100
  207. PyObject *tup;
  208. PyTypeObject *typ = Py_TYPE(obj);
  209. int i, removelast = 0;
  210. Py_ssize_t len;
  211. char buf[REPR_BUFFER_SIZE];
  212. char *endofbuf, *pbuf = buf;
  213. /* pointer to end of writeable buffer; safes space for "...)\0" */
  214. endofbuf= &buf[REPR_BUFFER_SIZE-5];
  215. if ((tup = make_tuple(obj)) == NULL) {
  216. return NULL;
  217. }
  218. /* "typename(", limited to TYPE_MAXSIZE */
  219. len = strlen(typ->tp_name) > TYPE_MAXSIZE ? TYPE_MAXSIZE :
  220. strlen(typ->tp_name);
  221. strncpy(pbuf, typ->tp_name, len);
  222. pbuf += len;
  223. *pbuf++ = '(';
  224. for (i=0; i < VISIBLE_SIZE(obj); i++) {
  225. PyObject *val, *repr;
  226. char *cname, *crepr;
  227. cname = typ->tp_members[i].name;
  228. val = PyTuple_GetItem(tup, i);
  229. if (cname == NULL || val == NULL) {
  230. return NULL;
  231. }
  232. repr = PyObject_Repr(val);
  233. if (repr == NULL) {
  234. Py_DECREF(tup);
  235. return NULL;
  236. }
  237. crepr = PyString_AsString(repr);
  238. if (crepr == NULL) {
  239. Py_DECREF(tup);
  240. Py_DECREF(repr);
  241. return NULL;
  242. }
  243. /* + 3: keep space for "=" and ", " */
  244. len = strlen(cname) + strlen(crepr) + 3;
  245. if ((pbuf+len) <= endofbuf) {
  246. strcpy(pbuf, cname);
  247. pbuf += strlen(cname);
  248. *pbuf++ = '=';
  249. strcpy(pbuf, crepr);
  250. pbuf += strlen(crepr);
  251. *pbuf++ = ',';
  252. *pbuf++ = ' ';
  253. removelast = 1;
  254. Py_DECREF(repr);
  255. }
  256. else {
  257. strcpy(pbuf, "...");
  258. pbuf += 3;
  259. removelast = 0;
  260. Py_DECREF(repr);
  261. break;
  262. }
  263. }
  264. Py_DECREF(tup);
  265. if (removelast) {
  266. /* overwrite last ", " */
  267. pbuf-=2;
  268. }
  269. *pbuf++ = ')';
  270. *pbuf = '\0';
  271. return PyString_FromString(buf);
  272. }
  273. static PyObject *
  274. structseq_concat(PyStructSequence *obj, PyObject *b)
  275. {
  276. PyObject *tup, *result;
  277. tup = make_tuple(obj);
  278. result = PySequence_Concat(tup, b);
  279. Py_DECREF(tup);
  280. return result;
  281. }
  282. static PyObject *
  283. structseq_repeat(PyStructSequence *obj, Py_ssize_t n)
  284. {
  285. PyObject *tup, *result;
  286. tup = make_tuple(obj);
  287. result = PySequence_Repeat(tup, n);
  288. Py_DECREF(tup);
  289. return result;
  290. }
  291. static int
  292. structseq_contains(PyStructSequence *obj, PyObject *o)
  293. {
  294. PyObject *tup;
  295. int result;
  296. tup = make_tuple(obj);
  297. if (!tup)
  298. return -1;
  299. result = PySequence_Contains(tup, o);
  300. Py_DECREF(tup);
  301. return result;
  302. }
  303. static long
  304. structseq_hash(PyObject *obj)
  305. {
  306. PyObject *tup;
  307. long result;
  308. tup = make_tuple((PyStructSequence*) obj);
  309. if (!tup)
  310. return -1;
  311. result = PyObject_Hash(tup);
  312. Py_DECREF(tup);
  313. return result;
  314. }
  315. static PyObject *
  316. structseq_richcompare(PyObject *obj, PyObject *o2, int op)
  317. {
  318. PyObject *tup, *result;
  319. tup = make_tuple((PyStructSequence*) obj);
  320. result = PyObject_RichCompare(tup, o2, op);
  321. Py_DECREF(tup);
  322. return result;
  323. }
  324. static PyObject *
  325. structseq_reduce(PyStructSequence* self)
  326. {
  327. PyObject* tup;
  328. PyObject* dict;
  329. PyObject* result;
  330. Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields;
  331. int i;
  332. n_fields = REAL_SIZE(self);
  333. n_visible_fields = VISIBLE_SIZE(self);
  334. n_unnamed_fields = UNNAMED_FIELDS(self);
  335. tup = PyTuple_New(n_visible_fields);
  336. if (!tup) {
  337. return NULL;
  338. }
  339. dict = PyDict_New();
  340. if (!dict) {
  341. Py_DECREF(tup);
  342. return NULL;
  343. }
  344. for (i = 0; i < n_visible_fields; i++) {
  345. Py_INCREF(self->ob_item[i]);
  346. PyTuple_SET_ITEM(tup, i, self->ob_item[i]);
  347. }
  348. for (; i < n_fields; i++) {
  349. char *n = Py_TYPE(self)->tp_members[i-n_unnamed_fields].name;
  350. PyDict_SetItemString(dict, n,
  351. self->ob_item[i]);
  352. }
  353. result = Py_BuildValue("(O(OO))", Py_TYPE(self), tup, dict);
  354. Py_DECREF(tup);
  355. Py_DECREF(dict);
  356. return result;
  357. }
  358. static PySequenceMethods structseq_as_sequence = {
  359. (lenfunc)structseq_length,
  360. (binaryfunc)structseq_concat, /* sq_concat */
  361. (ssizeargfunc)structseq_repeat, /* sq_repeat */
  362. (ssizeargfunc)structseq_item, /* sq_item */
  363. (ssizessizeargfunc)structseq_slice, /* sq_slice */
  364. 0, /* sq_ass_item */
  365. 0, /* sq_ass_slice */
  366. (objobjproc)structseq_contains, /* sq_contains */
  367. };
  368. static PyMappingMethods structseq_as_mapping = {
  369. (lenfunc)structseq_length,
  370. (binaryfunc)structseq_subscript,
  371. };
  372. static PyMethodDef structseq_methods[] = {
  373. {"__reduce__", (PyCFunction)structseq_reduce,
  374. METH_NOARGS, NULL},
  375. {NULL, NULL}
  376. };
  377. static PyTypeObject _struct_sequence_template = {
  378. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  379. NULL, /* tp_name */
  380. 0, /* tp_basicsize */
  381. 0, /* tp_itemsize */
  382. (destructor)structseq_dealloc, /* tp_dealloc */
  383. 0, /* tp_print */
  384. 0, /* tp_getattr */
  385. 0, /* tp_setattr */
  386. 0, /* tp_compare */
  387. (reprfunc)structseq_repr, /* tp_repr */
  388. 0, /* tp_as_number */
  389. &structseq_as_sequence, /* tp_as_sequence */
  390. &structseq_as_mapping, /* tp_as_mapping */
  391. structseq_hash, /* tp_hash */
  392. 0, /* tp_call */
  393. 0, /* tp_str */
  394. 0, /* tp_getattro */
  395. 0, /* tp_setattro */
  396. 0, /* tp_as_buffer */
  397. Py_TPFLAGS_DEFAULT, /* tp_flags */
  398. NULL, /* tp_doc */
  399. 0, /* tp_traverse */
  400. 0, /* tp_clear */
  401. structseq_richcompare, /* tp_richcompare */
  402. 0, /* tp_weaklistoffset */
  403. 0, /* tp_iter */
  404. 0, /* tp_iternext */
  405. structseq_methods, /* tp_methods */
  406. NULL, /* tp_members */
  407. 0, /* tp_getset */
  408. 0, /* tp_base */
  409. 0, /* tp_dict */
  410. 0, /* tp_descr_get */
  411. 0, /* tp_descr_set */
  412. 0, /* tp_dictoffset */
  413. 0, /* tp_init */
  414. 0, /* tp_alloc */
  415. structseq_new, /* tp_new */
  416. };
  417. void
  418. PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
  419. {
  420. PyObject *dict;
  421. PyMemberDef* members;
  422. int n_members, n_unnamed_members, i, k;
  423. #ifdef Py_TRACE_REFS
  424. /* if the type object was chained, unchain it first
  425. before overwriting its storage */
  426. if (type->_ob_next) {
  427. _Py_ForgetReference((PyObject*)type);
  428. }
  429. #endif
  430. n_unnamed_members = 0;
  431. for (i = 0; desc->fields[i].name != NULL; ++i)
  432. if (desc->fields[i].name == PyStructSequence_UnnamedField)
  433. n_unnamed_members++;
  434. n_members = i;
  435. memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject));
  436. type->tp_name = desc->name;
  437. type->tp_doc = desc->doc;
  438. type->tp_basicsize = sizeof(PyStructSequence)+
  439. sizeof(PyObject*)*(n_members-1);
  440. type->tp_itemsize = 0;
  441. members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1);
  442. if (members == NULL)
  443. return;
  444. for (i = k = 0; i < n_members; ++i) {
  445. if (desc->fields[i].name == PyStructSequence_UnnamedField)
  446. continue;
  447. members[k].name = desc->fields[i].name;
  448. members[k].type = T_OBJECT;
  449. members[k].offset = offsetof(PyStructSequence, ob_item)
  450. + i * sizeof(PyObject*);
  451. members[k].flags = READONLY;
  452. members[k].doc = desc->fields[i].doc;
  453. k++;
  454. }
  455. members[k].name = NULL;
  456. type->tp_members = members;
  457. if (PyType_Ready(type) < 0)
  458. return;
  459. Py_INCREF(type);
  460. dict = type->tp_dict;
  461. #define SET_DICT_FROM_INT(key, value) \
  462. do { \
  463. PyObject *v = PyInt_FromLong((long) value); \
  464. if (v != NULL) { \
  465. PyDict_SetItemString(dict, key, v); \
  466. Py_DECREF(v); \
  467. } \
  468. } while (0)
  469. SET_DICT_FROM_INT(visible_length_key, desc->n_in_sequence);
  470. SET_DICT_FROM_INT(real_length_key, n_members);
  471. SET_DICT_FROM_INT(unnamed_fields_key, n_unnamed_members);
  472. }