|
@@ -12,7 +12,11 @@
|
|
|
|
|
|
|
|
|
/*
|
|
|
- * String iterator for codec output.
|
|
|
+ * Iterator helpers.
|
|
|
+ */
|
|
|
+
|
|
|
+/*
|
|
|
+ * String iterator for encoder output.
|
|
|
*
|
|
|
* Yields one string (one or more lines) at a time.
|
|
|
*/
|
|
@@ -48,6 +52,7 @@ StringIterator_next (StringIteratorObject *it_obj)
|
|
|
return (rdf_obj);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/*
|
|
|
* String iterator type.
|
|
|
*
|
|
@@ -66,6 +71,57 @@ PyTypeObject StringIteratorType = {
|
|
|
};
|
|
|
|
|
|
|
|
|
+/*
|
|
|
+ * Graph iterator.
|
|
|
+ *
|
|
|
+ * Yields one triple at a time.
|
|
|
+ */
|
|
|
+typedef struct {
|
|
|
+ PyObject_HEAD
|
|
|
+ LSUP_GraphIterator *it;
|
|
|
+ LSUP_Triple *spo;
|
|
|
+} GraphIteratorObject;
|
|
|
+
|
|
|
+
|
|
|
+static void
|
|
|
+GraphIterator_dealloc (GraphIteratorObject *it_obj)
|
|
|
+{
|
|
|
+ LSUP_graph_iter_free (it_obj->it);
|
|
|
+ free (it_obj->spo);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static PyObject *
|
|
|
+GraphIterator_next (GraphIteratorObject *it_obj)
|
|
|
+{
|
|
|
+ LSUP_rc rc = LSUP_graph_iter_next (it_obj->it, it_obj->spo);
|
|
|
+ if (rc != LSUP_OK) {
|
|
|
+ if (rc != LSUP_END)
|
|
|
+ PyErr_SetString (PyExc_ValueError, "Error encoding graph.");
|
|
|
+
|
|
|
+ // If not an error, this raises StopIteration.
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ return build_triple (it_obj->spo);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ * Graph iterator type.
|
|
|
+ */
|
|
|
+PyTypeObject GraphIteratorType = {
|
|
|
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
|
|
+ .tp_name = "graph.GraphIterator",
|
|
|
+ .tp_basicsize = sizeof (GraphIteratorObject),
|
|
|
+ .tp_itemsize = 0,
|
|
|
+ .tp_flags = Py_TPFLAGS_DEFAULT,
|
|
|
+ .tp_dealloc = (destructor) GraphIterator_dealloc,
|
|
|
+ .tp_iter = PyObject_SelfIter,
|
|
|
+ .tp_iternext = (iternextfunc) GraphIterator_next,
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
/*
|
|
|
* Graph stuff.
|
|
|
*/
|
|
@@ -294,18 +350,92 @@ finalize:
|
|
|
}
|
|
|
|
|
|
|
|
|
-// TODO
|
|
|
-static int Graph_remove (PyObject *self, PyObject *s, PyObject *p, PyObject *o)
|
|
|
+inline static int build_trp_pattern (PyObject *args, LSUP_Term *spo[])
|
|
|
{
|
|
|
+ PyObject *s_obj, *p_obj, *o_obj;
|
|
|
+
|
|
|
+ if (! (PyArg_ParseTuple (args, "OOO", &s_obj, &p_obj, &o_obj)))
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ if (s_obj != Py_None && !PyObject_TypeCheck (s_obj, &TermType)) {
|
|
|
+ PyErr_SetString (PyExc_TypeError, "Subject must be a term or None.");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if (p_obj != Py_None && !PyObject_TypeCheck (p_obj, &TermType)) {
|
|
|
+ PyErr_SetString (PyExc_TypeError, "Predicate must be a term or None.");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if (o_obj != Py_None && !PyObject_TypeCheck (o_obj, &TermType)) {
|
|
|
+ PyErr_SetString (PyExc_TypeError, "Object must be a term or None.");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ spo[0] = s_obj != Py_None ? ((TermObject *)s_obj)->ob_struct : NULL;
|
|
|
+ spo[1] = s_obj != Py_None ? ((TermObject *)p_obj)->ob_struct : NULL;
|
|
|
+ spo[2] = s_obj != Py_None ? ((TermObject *)o_obj)->ob_struct : NULL;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
|
|
|
-// TODO
|
|
|
-static PyObject *Graph_lookup (
|
|
|
- PyObject *self, PyObject *s, PyObject *p, PyObject *o)
|
|
|
+static PyObject *Graph_remove (PyObject *self, PyObject *args)
|
|
|
{
|
|
|
- return NULL;
|
|
|
+ LSUP_rc rc;
|
|
|
+ LSUP_Term *spo[3];
|
|
|
+
|
|
|
+ rc = build_trp_pattern (args, spo);
|
|
|
+ if (rc < 0) goto finally;
|
|
|
+
|
|
|
+ size_t ct;
|
|
|
+ rc = LSUP_graph_remove (
|
|
|
+ ((GraphObject *)self)->ob_struct, spo[0], spo[1], spo[2], &ct);
|
|
|
+
|
|
|
+ if (rc < 0) {
|
|
|
+ // TODO implement strerror for more details.
|
|
|
+ PyErr_SetString (PyExc_SystemError, "Error removing triples.");
|
|
|
+ goto finally;
|
|
|
+ }
|
|
|
+ TRACE ("Removed %lu triples.", ct);
|
|
|
+
|
|
|
+finally:
|
|
|
+ if (rc < 0) return NULL;
|
|
|
+
|
|
|
+ Py_RETURN_NONE;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static PyObject *Graph_lookup (PyObject *self, PyObject *args)
|
|
|
+{
|
|
|
+ LSUP_rc rc;
|
|
|
+ GraphIteratorObject *it_obj = NULL;
|
|
|
+ LSUP_Term *spo[3];
|
|
|
+
|
|
|
+ rc = build_trp_pattern (args, spo);
|
|
|
+ if (UNLIKELY (rc < 0)) goto finally;
|
|
|
+
|
|
|
+ size_t ct;
|
|
|
+ LSUP_GraphIterator *it = LSUP_graph_lookup (
|
|
|
+ ((GraphObject *)self)->ob_struct, spo[0], spo[1], spo[2], &ct);
|
|
|
+ if (UNLIKELY (!it)) {
|
|
|
+ // TODO implement LSUP_strerror for more details.
|
|
|
+ PyErr_SetString (PyExc_SystemError, "Error looking up triples.");
|
|
|
+ rc = -1;
|
|
|
+ goto finally;
|
|
|
+ }
|
|
|
+ TRACE ("Found %lu triples.", ct);
|
|
|
+
|
|
|
+ // Initialize the generator object.
|
|
|
+ it_obj = PyObject_New (
|
|
|
+ GraphIteratorObject, &GraphIteratorType);
|
|
|
+ if (UNLIKELY (!it_obj)) goto finally;
|
|
|
+
|
|
|
+ it_obj->it = it;
|
|
|
+ it_obj->spo = NULL;
|
|
|
+
|
|
|
+ Py_INCREF (it_obj);
|
|
|
+
|
|
|
+finally:
|
|
|
+ return (PyObject *)it_obj;
|
|
|
}
|
|
|
|
|
|
|