py_triple.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #ifndef _PY_TRIPLE_OBJ_H
  2. #define _PY_TRIPLE_OBJ_H
  3. #define PY_SSIZE_T_CLEAN
  4. #include <Python.h>
  5. #include <structmember.h>
  6. #include "py_term.h"
  7. typedef struct {
  8. PyObject_HEAD
  9. LSUP_Triple * ob_struct;
  10. PyObject *s;
  11. PyObject *p;
  12. PyObject *o;
  13. } TripleObject;
  14. static int
  15. Triple_init (TripleObject *self, PyObject *args)
  16. {
  17. PyObject *s = NULL, *p = NULL, *o = NULL, *tmp;
  18. if (! PyArg_ParseTuple (args, "OOO", &s, &p, &o)) return -1;
  19. // TODO check for null s, p, o
  20. tmp = self->s;
  21. Py_INCREF(s);
  22. self->s = s;
  23. Py_XDECREF(tmp);
  24. tmp = self->p;
  25. Py_INCREF(p);
  26. self->p = p;
  27. Py_XDECREF(tmp);
  28. tmp = self->o;
  29. Py_INCREF(o);
  30. self->o = o;
  31. Py_XDECREF(tmp);
  32. self->ob_struct = LSUP_triple_new (
  33. ((TermObject *) self->s)->ob_struct,
  34. ((TermObject *) self->p)->ob_struct,
  35. ((TermObject *) self->o)->ob_struct);
  36. if (!self->ob_struct) {
  37. PyErr_SetString (PyExc_ValueError, "Could not create triple.");
  38. return -1;
  39. }
  40. return 0;
  41. }
  42. static void
  43. Triple_dealloc (TripleObject *self)
  44. {
  45. Py_XDECREF(self->s);
  46. Py_XDECREF(self->p);
  47. Py_XDECREF(self->o);
  48. free (self->ob_struct); // Term pointers were allocated independently.
  49. Py_TYPE (self)->tp_free ((PyObject *) self);
  50. }
  51. static PyMemberDef Triple_members[] = {
  52. {"s", T_OBJECT_EX, offsetof(TripleObject, s), 0, "Triple subject."},
  53. {"p", T_OBJECT_EX, offsetof(TripleObject, p), 0, "Triple predicate."},
  54. {"o", T_OBJECT_EX, offsetof(TripleObject, o), 0, "Triple object."},
  55. {NULL}
  56. };
  57. static PyObject *
  58. Triple_richcmp (PyObject *obj1, PyObject *obj2, int op)
  59. {
  60. // Only equality and non-equality supported.
  61. if (op != Py_EQ && op != Py_NE) Py_RETURN_NOTIMPLEMENTED;
  62. LSUP_Triple *t1 = ((TripleObject *) obj1)->ob_struct;
  63. LSUP_Triple *t2 = ((TripleObject *) obj2)->ob_struct;
  64. if (
  65. (
  66. LSUP_term_equals (t1->s, t2->s) &&
  67. LSUP_term_equals (t1->p, t2->p) &&
  68. LSUP_term_equals (t1->o, t2->o)
  69. ) ^ (op == Py_NE)
  70. ) Py_RETURN_TRUE;
  71. Py_RETURN_FALSE;
  72. }
  73. static Py_hash_t
  74. Triple_hash (PyObject *self)
  75. { return LSUP_triple_hash (((TripleObject *)self)->ob_struct); }
  76. PyTypeObject TripleType = {
  77. PyVarObject_HEAD_INIT(NULL, 0)
  78. .tp_name = "triple.Triple",
  79. .tp_doc = "RDF triple.",
  80. .tp_basicsize = sizeof(TripleObject),
  81. .tp_itemsize = 0,
  82. .tp_flags = Py_TPFLAGS_DEFAULT,
  83. .tp_new = PyType_GenericNew,
  84. .tp_init = (initproc) Triple_init,
  85. .tp_dealloc = (destructor) Triple_dealloc,
  86. .tp_members = Triple_members,
  87. .tp_richcompare = Triple_richcmp,
  88. .tp_hash = Triple_hash,
  89. };
  90. /** @brief Build a triple object from a LSUP_Triple struct.
  91. */
  92. PyObject *
  93. build_triple (LSUP_Triple *spo)
  94. {
  95. PyObject
  96. *s_obj = build_term (spo->s),
  97. *p_obj = build_term (spo->p),
  98. *o_obj = build_term (spo->o);
  99. log_trace ("Building triple.");
  100. PyObject *trp_args = Py_BuildValue ("OOO", s_obj, p_obj, o_obj);
  101. if (UNLIKELY (!trp_args)) {
  102. PyErr_SetString (PyExc_SystemError, "Error building triple args.");
  103. return NULL;
  104. }
  105. PyObject *spo_obj = PyObject_CallObject ((PyObject *)&TripleType, trp_args);
  106. Py_DECREF (trp_args);
  107. if (UNLIKELY (!spo_obj)) {
  108. PyErr_SetString (PyExc_SystemError, "Error building triple object.");
  109. return NULL;
  110. }
  111. return spo_obj;
  112. }
  113. #endif