Просмотр исходного кода

Some important Graph and Term changes:

* Use `char*` for graph URI in ``LSUP_graph_new()` and
  LSUP_graph_set_uri()`;
* Allow undefined type terms;
* `LSUP_nsmap_normalize_uri()` returns original URI string if ns is not
  mapped.
scossu 1 неделя назад
Родитель
Сommit
0c5f1ddd04
8 измененных файлов с 73 добавлено и 55 удалено
  1. 10 27
      cpython/py_graph.h
  2. 10 6
      include/graph.h
  3. 2 2
      include/namespace.h
  4. 12 8
      src/graph.c
  5. 6 2
      src/namespace.c
  6. 13 6
      src/term.c
  7. 3 4
      test/test_graph.c
  8. 17 0
      test/test_term.c

+ 10 - 27
cpython/py_graph.h

@@ -135,28 +135,14 @@ Graph_init (GraphObject *self, PyObject *args, PyObject *kwargs)
 {
     unsigned char store_type;
     PyObject *uri_obj = NULL;
-    LSUP_Term *uri = NULL, *src_uri = NULL;
+    char *uri_str = NULL;
 
-    static char *kwlist[] = {"", "uri_obj", NULL};
+    static char *kwlist[] = {"", "uri_str", NULL};
 
     if (!PyArg_ParseTupleAndKeywords (
-            args, kwargs, "b|O", kwlist, &store_type, &uri_obj))
+            args, kwargs, "b|s", kwlist, &store_type, &uri_str))
         return -1;
 
-    if (uri_obj) {
-        if (!PyObject_TypeCheck (uri_obj, &TermType)) {
-            PyErr_SetString (PyExc_TypeError, "uri is not a Term type.");
-            return -1;
-        }
-        src_uri = ((TermObject *) uri_obj)->ob_struct;
-        uri = LSUP_iriref_new (src_uri->data, LSUP_iriref_nsm (src_uri));
-        if (! LSUP_IS_IRI (uri)) {
-            PyErr_SetString (PyExc_TypeError, "uri is not a IRIREF type.");
-            return -1;
-        }
-
-    }
-
     // Set up the store if a function for that is defined.
     const LSUP_StoreInt *sif = LSUP_store_int (store_type);
     if (UNLIKELY (!sif)) {
@@ -177,12 +163,12 @@ Graph_init (GraphObject *self, PyObject *args, PyObject *kwargs)
     }
 
     // TODO Make store ID, nsm and initial size accessible.
-    self->ob_struct = LSUP_graph_new (store, uri, NULL);
+    self->ob_struct = LSUP_graph_new (store, uri_str, NULL);
     if (!self->ob_struct) {
         PyErr_SetString (PyExc_ValueError, "Could not create graph.");
         return -1;
     }
-    if (uri) LSUP_term_free (uri);
+    if (uri_str) free (uri_str);
 
     return 0;
 }
@@ -207,16 +193,13 @@ Graph_get_uri (GraphObject *self, void *closure)
 
 
 static int
-Graph_set_uri (GraphObject *self, PyObject *value, void *closure)
+Graph_set_uri (GraphObject *self, PyObject *args)
 {
-    if (!PyObject_TypeCheck (value, &TermType)) {
-        PyErr_SetString (PyExc_TypeError, "URI is not a Term type.");
-        return -1;
-    }
-    LSUP_Term *gr_uri = ((TermObject*)value)->ob_struct;
-    LOG_DEBUG("New graph URI: %s", (gr_uri->data));
+    char *uri_str = NULL;
+    if (! PyArg_ParseTuple (args, "s", &uri_str)) return NULL;
 
-    LSUP_rc rc = LSUP_graph_set_uri (self->ob_struct, LSUP_term_copy (gr_uri));
+    LSUP_rc rc = LSUP_graph_set_uri (self->ob_struct, uri_str);
+    free (uri_str);
 
     return rc == LSUP_OK ? 0 : -1;
 }

+ 10 - 6
include/graph.h

@@ -30,9 +30,9 @@ typedef struct graph_iter_t LSUP_GraphIterator;
  * #LSUP_store_new(), or NULL; in the latter case, it defaults to a temporary
  * HTable store that is freed together with the graph.
  *
- * @param[in] uri URI of the new graph. If NULL, a UUID4 URN is generated. The
- *  term is copied into the graph and may be freed after this function is
- *  called.
+ * @param[in] uri_str URI string of the new graph. If namespace-prefixed, it
+ *  will resolve using the provided `nsm` parameter. If NULL, a UUID4 URN is
+ *  generated.
  *
  * @param[in] nsm Namespace map to use for an in-memory graph. This is ignored
  *  by graphs backed by permanent stores, which handle their own namespace map.
@@ -42,7 +42,7 @@ typedef struct graph_iter_t LSUP_GraphIterator;
  * @return New graph, or NULL on error. Must be freed with #LSUP_graph_free().
  */
 LSUP_Graph *
-LSUP_graph_new (LSUP_Store *store, const LSUP_Term *uri, LSUP_NSMap *nsm);
+LSUP_graph_new (LSUP_Store *store, const char *uri_str, LSUP_NSMap *nsm);
 
 
 /** @brief Create a temp graph from stored triples.
@@ -175,6 +175,9 @@ LSUP_graph_equals (const LSUP_Graph *gr1, const LSUP_Graph *gr2);
 
 
 /** @brief Read-only graph URI.
+ *
+ * Note that, while #LSUP_graph_new() and #LSUP_graph_set_uri() expect a
+ *  string, this function returns the complete #LSUP_Term structure.
  *
  * To change the graph URI, use #LSUP_graph_set_uri.
  */
@@ -199,12 +202,13 @@ LSUP_graph_store (const LSUP_Graph *gr);
  *
  * @param[in] gr Graph handle.
  *
- * @param[in] uri IRI handle. The graph takes ownership of the handle.
+ * @param[in] uri_str New URI string. If namespace-prefixed, it will be
+ *  resolved according to the graph's namespace map.
  *
  * @return LSUP_OK on success; <0 on error.
  */
 LSUP_rc
-LSUP_graph_set_uri (LSUP_Graph *gr, LSUP_Term *uri);
+LSUP_graph_set_uri (LSUP_Graph *gr, const char *uri_str);
 
 
 /** @brief Get the namespace map for an in-memory graph.

+ 2 - 2
include/namespace.h

@@ -110,7 +110,7 @@ LSUP_nsmap_get_pfx (const LSUP_NSMap *map, const char *ns);
  *  namespace is not in the map or an error occurred, this will be NULL. The
  *  caller is in charge of freeing the memory.
  *
- * @return LSUP_OK on success, LSUP_VALUE_ERR if no entry was found in the map,
+ * @return LSUP_OK on success, LSUP_NORESULT if no entry was found in the map,
  *  LSUP_MEM_ERR if a memory allocation error ocurred.
  */
 LSUP_rc
@@ -120,7 +120,7 @@ LSUP_nsmap_normalize_uri (
 
 /** @brief Convert a FQ URI string to a prefixed string if the prefix is found.
  *
- * TODO Note that this function does not attempt to find the longest or
+ * @todo Note that this function does not attempt to find the longest or
  * shortest namespace prefix in case of conflicts (e.g. when both
  * `http://example.edu/` and `http://example.edu/data/` are mapped and
  * `http://example.edu/data/51937642` is being denormalized). In such

+ 12 - 8
src/graph.c

@@ -42,7 +42,7 @@ check_backend (LSUP_StoreType be)
  */
 
 LSUP_Graph *
-LSUP_graph_new (LSUP_Store *store, const LSUP_Term *uri, LSUP_NSMap *nsm)
+LSUP_graph_new (LSUP_Store *store, const char *uri_str, LSUP_NSMap *nsm)
 {
     // Create a HTable graph by default.
     if (!store) store = LSUP_store_new (LSUP_STORE_HTABLE, NULL, 0);
@@ -50,7 +50,9 @@ LSUP_graph_new (LSUP_Store *store, const LSUP_Term *uri, LSUP_NSMap *nsm)
     LSUP_Graph *gr;
     MALLOC_GUARD (gr, NULL);
 
-    gr->uri = uri? LSUP_term_copy (uri) : LSUP_iriref_new (NULL, NULL);
+    gr->uri =
+        uri_str? LSUP_iriref_new (uri_str, nsm) :
+        LSUP_iriref_new (NULL, NULL);
     gr->store = store;
 
     if (gr->store->sif->features & LSUP_STORE_PERM) gr->nsm = NULL;
@@ -69,7 +71,7 @@ LSUP_graph_get_txn (
     void *it = store->sif->lookup_fn (
             store->data, NULL, NULL, NULL, sc, NULL, NULL);
 
-    LSUP_Graph *gr = LSUP_graph_new (NULL, uri, NULL);
+    LSUP_Graph *gr = LSUP_graph_new (NULL, uri->data, NULL);
     LSUP_BufferTriple *sspo = BTRP_DUMMY;
     void *add_it = LSUP_graph_add_init_txn (txn, gr);
 
@@ -243,15 +245,17 @@ LSUP_graph_store (const LSUP_Graph *gr)
 
 
 LSUP_rc
-LSUP_graph_set_uri (LSUP_Graph *gr, LSUP_Term *uri)
+LSUP_graph_set_uri (LSUP_Graph *gr, const char *uri_str)
 {
-    if (!LSUP_IS_IRI (uri)) {
-        log_error ("Term provided is not a IRI.");
-        return LSUP_VALUE_ERR;
+    LSUP_rc rc = LSUP_OK;
+
+    LSUP_Term *uri = LSUP_iriref_new (uri_str, gr->nsm);
+    if (UNLIKELY (!uri)) {
+        rc = LSUP_MEM_ERR;
+        goto finally;
     }
 
     // Update context for triples in the graph.
-    LSUP_rc rc = LSUP_OK;
     LSUP_Buffer *old_sc = NULL, *new_sc = NULL;
 
     if (gr->store->sif->features & LSUP_STORE_CTX) {

+ 6 - 2
src/namespace.c

@@ -173,8 +173,12 @@ LSUP_nsmap_normalize_uri (
 
         rc = LSUP_OK;
     } else {
-        log_error ("No NS prefix found in map to normalize %s", pfx_uri);
-        rc = LSUP_VALUE_ERR;
+        log_warn ("No NS prefix found in map to normalize %s", pfx_uri);
+
+        fq_uri = malloc (strlen(pfx_uri) + 1);
+        if (UNLIKELY (! (fq_uri))) return LSUP_MEM_ERR;
+        strcpy (fq_uri, pfx_uri);
+        rc = LSUP_NORESULT;
     }
 
     *fq_uri_p = fq_uri;

+ 13 - 6
src/term.c

@@ -171,10 +171,7 @@ LSUP_term_new (
     LSUP_Term *term;
     CALLOC_GUARD (term, NULL);
 
-    // If undefined, just set the type.
-    if (type == LSUP_TERM_UNDEFINED) term->type = type;
-
-    else if (UNLIKELY (term_init (
+    if (UNLIKELY (term_init (
                     term, type, data, metadata) != LSUP_OK)) {
         free (term);
         return NULL;
@@ -322,7 +319,7 @@ LSUP_term_serialize (const LSUP_Term *term)
 
         if (LSUP_nsmap_normalize_uri (
             term->iri_info->nsm, term->data, &fq_uri
-        ) != LSUP_OK) return NULL;
+        ) < LSUP_OK) return NULL;
 
         tmp_term = LSUP_iriref_new (fq_uri, NULL);
         free (fq_uri);
@@ -754,7 +751,17 @@ term_init (
         LSUP_Term *term, LSUP_TermType type,
         const char *data, void *metadata)
 {
-    // This can never be LSUP_TERM_UNDEFINED.
+    // Undefined type. Make quick work of it.
+    if (type == LSUP_TERM_UNDEFINED) {
+        term->type = type;
+        if (data) {
+            term->data = malloc (strlen (data) + 1);
+            if (UNLIKELY (!term->data)) return LSUP_MEM_ERR;
+            strcpy (term->data, data);
+        }
+        return LSUP_OK;
+    }
+
     if (type < MIN_VALID_TYPE || type > MAX_VALID_TYPE) {
         log_error ("%d is not a valid term type.", type);
         return LSUP_VALUE_ERR;

+ 3 - 4
test/test_graph.c

@@ -20,7 +20,7 @@ _graph_new (LSUP_StoreType type)
     }
     ASSERT (gr != NULL, "Error creating graph!");
 
-    EXPECT_PASS (LSUP_graph_set_uri (gr, LSUP_iriref_new ("urn:gr:1", NULL)));
+    EXPECT_PASS (LSUP_graph_set_uri (gr, "urn:gr:1"));
     EXPECT_STR_EQ (LSUP_graph_uri (gr)->data, "urn:gr:1");
 
     // Check that setup function is idempotent with clear == false.
@@ -476,7 +476,7 @@ _graph_relative (LSUP_StoreType type)
         type == LSUP_STORE_HTABLE ? NULL
         : LSUP_store_new (type, NULL, 0);
 
-    LSUP_Graph *gr = LSUP_graph_new (store, c, NULL);
+    LSUP_Graph *gr = LSUP_graph_new (store, c->data, NULL);
 
     size_t ct;
     LSUP_graph_add (gr, spo, &ct);
@@ -492,8 +492,7 @@ _graph_relative (LSUP_StoreType type)
     spo[0]->o = o2;
     LSUP_term_free (o);
 
-    LSUP_graph_set_uri (gr, LSUP_iriref_new (
-                "http://onto.knowledgetx.com/gr2/", NULL));
+    LSUP_graph_set_uri (gr, "http://onto.knowledgetx.com/gr2/");
     LSUP_term_free (c);
 
     ASSERT (LSUP_graph_contains (gr, rel_spo), "Relative triple not found!");

+ 17 - 0
test/test_term.c

@@ -215,6 +215,22 @@ static int test_literal()
     return 0;
 }
 
+static int test_undefined()
+{
+    LSUP_Term *undef1 = LSUP_term_new (LSUP_TERM_UNDEFINED, NULL, NULL);
+    ASSERT (undef1 != NULL, "Error creating undefined term without data!");
+
+    char *data = "bogus";
+    LSUP_Term *undef2 = LSUP_term_new (LSUP_TERM_UNDEFINED, data, NULL);
+    ASSERT (undef2 != NULL, "Error creating undefined term with data!");
+    EXPECT_STR_EQ (undef2->data, data);
+
+    LSUP_term_free (undef1);
+    LSUP_term_free (undef2);
+
+    return 0;
+}
+
 static int test_term_copy()
 {
     LSUP_Term *uri1 = LSUP_iriref_new ("http://hello.org", NULL);
@@ -355,6 +371,7 @@ int term_tests() {
     RUN (test_iriref_parts);
     RUN (test_iriref_abs_rel);
     RUN (test_literal);
+    RUN (test_undefined);
     RUN (test_term_copy);
     RUN (test_term_serialize_deserialize);
     RUN (test_term_to_key);