Bläddra i källkod

Implement Python graph lookup & delete.

Stefano Cossu 4 år sedan
förälder
incheckning
8c649a1347
4 ändrade filer med 175 tillägg och 10 borttagningar
  1. 137 7
      cpython/py_graph.h
  2. 37 0
      cpython/py_triple.h
  3. 0 2
      src/graph.c
  4. 1 1
      src/namespace.c

+ 137 - 7
cpython/py_graph.h

@@ -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;
 }
 
 

+ 37 - 0
cpython/py_triple.h

@@ -115,4 +115,41 @@ PyTypeObject TripleType = {
     .tp_hash = Triple_hash,
 };
 
+
+/** @brief Build a triple object from a LSUP_Triple struct.
+ */
+PyObject *
+build_triple (LSUP_Triple *spo)
+{
+    PyObject *s_obj, *p_obj, *o_obj, *spo_obj, *term_args, *trp_args;
+
+    term_args = Py_BuildValue (
+            "bsss", spo->s->type, spo->s->data,
+            spo->s->datatype, spo->s->lang);
+    s_obj = PyObject_CallObject ((PyObject *)&TermType, term_args);
+    Py_DECREF (term_args);
+    if (UNLIKELY (!s_obj)) return NULL;
+
+    term_args = Py_BuildValue (
+            "bsss", spo->p->type, spo->p->data,
+            spo->p->datatype, spo->p->lang);
+    p_obj = PyObject_CallObject ((PyObject *)&TermType, term_args);
+    if (UNLIKELY (!p_obj)) return NULL;
+    Py_DECREF (term_args);
+
+    term_args = Py_BuildValue (
+            "bsss", spo->o->type, spo->o->data,
+            spo->o->datatype, spo->o->lang);
+    o_obj = PyObject_CallObject ((PyObject *)&TermType, term_args);
+    if (UNLIKELY (!o_obj)) return NULL;
+    Py_DECREF (term_args);
+
+    trp_args = Py_BuildValue ("OOO", s_obj, p_obj, o_obj);
+    spo_obj = PyObject_CallObject ((PyObject *)&TripleType, trp_args);
+    if (UNLIKELY (!spo_obj)) return NULL;
+    Py_DECREF (trp_args);
+
+    return spo_obj;
+}
+
 #endif

+ 0 - 2
src/graph.c

@@ -258,12 +258,10 @@ LSUP_graph_size (const Graph *gr)
     if (gr->store_type == LSUP_STORE_MEM)
         return LSUP_htstore_size (gr->ht_store);
     else {
-        LSUP_Triple *spo = TRP_DUMMY;
         size_t ct;
         LSUP_GraphIterator *it = LSUP_graph_lookup (gr, NULL, NULL, NULL, &ct);
 
         LSUP_graph_iter_free (it);
-        LSUP_triple_free (spo);
 
         return ct;
     }

+ 1 - 1
src/namespace.c

@@ -184,7 +184,7 @@ LSUP_nsmap_denormalize_uri (
     if (entry)
         *uri = malloc (strlen (entry->ns) + strlen (pfx_uri) - pfx_len - 1);
 
-    else strcpy (*uri, pfx_uri);
+    else *uri = strdup (pfx_uri);
 
     return LSUP_OK;
 }