cellobject.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /* Cell object implementation */
  2. #include "Python.h"
  3. #include "pycore_object.h"
  4. PyObject *
  5. PyCell_New(PyObject *obj)
  6. {
  7. PyCellObject *op;
  8. op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type);
  9. if (op == NULL)
  10. return NULL;
  11. op->ob_ref = Py_XNewRef(obj);
  12. _PyObject_GC_TRACK(op);
  13. return (PyObject *)op;
  14. }
  15. PyDoc_STRVAR(cell_new_doc,
  16. "cell([contents])\n"
  17. "--\n"
  18. "\n"
  19. "Create a new cell object.\n"
  20. "\n"
  21. " contents\n"
  22. " the contents of the cell. If not specified, the cell will be empty,\n"
  23. " and \n further attempts to access its cell_contents attribute will\n"
  24. " raise a ValueError.");
  25. static PyObject *
  26. cell_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
  27. {
  28. PyObject *return_value = NULL;
  29. PyObject *obj = NULL;
  30. if (!_PyArg_NoKeywords("cell", kwargs)) {
  31. goto exit;
  32. }
  33. /* min = 0: we allow the cell to be empty */
  34. if (!PyArg_UnpackTuple(args, "cell", 0, 1, &obj)) {
  35. goto exit;
  36. }
  37. return_value = PyCell_New(obj);
  38. exit:
  39. return return_value;
  40. }
  41. PyObject *
  42. PyCell_Get(PyObject *op)
  43. {
  44. if (!PyCell_Check(op)) {
  45. PyErr_BadInternalCall();
  46. return NULL;
  47. }
  48. PyObject *value = PyCell_GET(op);
  49. return Py_XNewRef(value);
  50. }
  51. int
  52. PyCell_Set(PyObject *op, PyObject *value)
  53. {
  54. if (!PyCell_Check(op)) {
  55. PyErr_BadInternalCall();
  56. return -1;
  57. }
  58. PyObject *old_value = PyCell_GET(op);
  59. PyCell_SET(op, Py_XNewRef(value));
  60. Py_XDECREF(old_value);
  61. return 0;
  62. }
  63. static void
  64. cell_dealloc(PyCellObject *op)
  65. {
  66. _PyObject_GC_UNTRACK(op);
  67. Py_XDECREF(op->ob_ref);
  68. PyObject_GC_Del(op);
  69. }
  70. static PyObject *
  71. cell_richcompare(PyObject *a, PyObject *b, int op)
  72. {
  73. /* neither argument should be NULL, unless something's gone wrong */
  74. assert(a != NULL && b != NULL);
  75. /* both arguments should be instances of PyCellObject */
  76. if (!PyCell_Check(a) || !PyCell_Check(b)) {
  77. Py_RETURN_NOTIMPLEMENTED;
  78. }
  79. /* compare cells by contents; empty cells come before anything else */
  80. a = ((PyCellObject *)a)->ob_ref;
  81. b = ((PyCellObject *)b)->ob_ref;
  82. if (a != NULL && b != NULL)
  83. return PyObject_RichCompare(a, b, op);
  84. Py_RETURN_RICHCOMPARE(b == NULL, a == NULL, op);
  85. }
  86. static PyObject *
  87. cell_repr(PyCellObject *op)
  88. {
  89. if (op->ob_ref == NULL)
  90. return PyUnicode_FromFormat("<cell at %p: empty>", op);
  91. return PyUnicode_FromFormat("<cell at %p: %.80s object at %p>",
  92. op, Py_TYPE(op->ob_ref)->tp_name,
  93. op->ob_ref);
  94. }
  95. static int
  96. cell_traverse(PyCellObject *op, visitproc visit, void *arg)
  97. {
  98. Py_VISIT(op->ob_ref);
  99. return 0;
  100. }
  101. static int
  102. cell_clear(PyCellObject *op)
  103. {
  104. Py_CLEAR(op->ob_ref);
  105. return 0;
  106. }
  107. static PyObject *
  108. cell_get_contents(PyCellObject *op, void *closure)
  109. {
  110. if (op->ob_ref == NULL)
  111. {
  112. PyErr_SetString(PyExc_ValueError, "Cell is empty");
  113. return NULL;
  114. }
  115. return Py_NewRef(op->ob_ref);
  116. }
  117. static int
  118. cell_set_contents(PyCellObject *op, PyObject *obj, void *Py_UNUSED(ignored))
  119. {
  120. Py_XSETREF(op->ob_ref, Py_XNewRef(obj));
  121. return 0;
  122. }
  123. static PyGetSetDef cell_getsetlist[] = {
  124. {"cell_contents", (getter)cell_get_contents,
  125. (setter)cell_set_contents, NULL},
  126. {NULL} /* sentinel */
  127. };
  128. PyTypeObject PyCell_Type = {
  129. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  130. "cell",
  131. sizeof(PyCellObject),
  132. 0,
  133. (destructor)cell_dealloc, /* tp_dealloc */
  134. 0, /* tp_vectorcall_offset */
  135. 0, /* tp_getattr */
  136. 0, /* tp_setattr */
  137. 0, /* tp_as_async */
  138. (reprfunc)cell_repr, /* tp_repr */
  139. 0, /* tp_as_number */
  140. 0, /* tp_as_sequence */
  141. 0, /* tp_as_mapping */
  142. 0, /* tp_hash */
  143. 0, /* tp_call */
  144. 0, /* tp_str */
  145. PyObject_GenericGetAttr, /* tp_getattro */
  146. 0, /* tp_setattro */
  147. 0, /* tp_as_buffer */
  148. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  149. cell_new_doc, /* tp_doc */
  150. (traverseproc)cell_traverse, /* tp_traverse */
  151. (inquiry)cell_clear, /* tp_clear */
  152. cell_richcompare, /* tp_richcompare */
  153. 0, /* tp_weaklistoffset */
  154. 0, /* tp_iter */
  155. 0, /* tp_iternext */
  156. 0, /* tp_methods */
  157. 0, /* tp_members */
  158. cell_getsetlist, /* tp_getset */
  159. 0, /* tp_base */
  160. 0, /* tp_dict */
  161. 0, /* tp_descr_get */
  162. 0, /* tp_descr_set */
  163. 0, /* tp_dictoffset */
  164. 0, /* tp_init */
  165. 0, /* tp_alloc */
  166. (newfunc)cell_new, /* tp_new */
  167. 0, /* tp_free */
  168. };