Pārlūkot izejas kodu

Move connection list functions to term and gaph modules.

Stefano Cossu 2 gadi atpakaļ
vecāks
revīzija
280a12890d
7 mainītis faili ar 300 papildinājumiem un 259 dzēšanām
  1. 0 92
      include/codec.h
  2. 33 0
      include/graph.h
  3. 91 0
      include/term.h
  4. 0 157
      src/codec.c
  5. 10 10
      src/codec/grammar_ttl.y
  6. 82 0
      src/graph.c
  7. 84 0
      src/term.c

+ 0 - 92
include/codec.h

@@ -39,18 +39,6 @@ typedef struct codec_iter_t {
          *              str_o;      // Temporary string.
 } LSUP_CodecIterator;
 
-/// Predicate and object list. Used for Turtle.
-typedef struct {
-    LSUP_Term **    p;              ///< NULL-terminated array of term handles.
-    LSUP_Term ***   o;              /**<
-                                      * NULL-terminated array of
-                                      * NULL-terminated arrays of term handles.
-                                      * The indices of the outer array are
-                                      * equal to the indices of the associated
-                                      * predicate in the predicate list.
-                                      */
-} LSUP_PredObjList;
-
 /// Parser state.
 typedef struct {
     LSUP_GraphIterator *    it;     ///< Iterator used to build the graph.
@@ -303,84 +291,4 @@ unescape_char (const char c)
 uint8_t *unescape_unicode (const uint8_t *esc_str, size_t size);
 
 
-/** @brief Add an object to an objct list.
- *
- * @param[in] ol Array of object handles to be added to. On success, this
- *  handle will be reallocated and the new address returned, so the passed
- *  handle should no longer be used. On failure, it remains unchanged and may
- *  be reused.
- *
- * @param[in] o Object to be added to the list. The object list will take
- *  ownership of the term.
- *
- * @return Reallocated list on success; NULL on failure.
- */
-LSUP_Term **
-LSUP_obj_list_add (LSUP_Term **ol, LSUP_Term *o);
-
-
-/** @brief New predicate-object list.
- *
- * @return a new empty predicate-object list.
- */
-LSUP_PredObjList *
-LSUP_pred_obj_list_new (void);
-
-
-/** @brief Free a predicate-object list.
- *
- * @param[in] pol Predicate-object list handle obtained with
- *  #LSUP_pred_obj_list_new().
- */
-void
-LSUP_pred_obj_list_free (LSUP_PredObjList *pol);
-
-
-/** @brief Add a predicate-object list pair to a PO list.
- *
- * @param[in] pol Predicate-object list handle obtained with
- *  #LSUP_pred_obj_list_new().
- *
- *  @param[in] p Predicate to be associated with the given object list. The
- *   PO structure takes ownership of the term.
- *
- *  @param[in] o NULL-terminated array of object term handles to be associated
- *   with the given predicate. The PO structire takes ownership of the whole
- *   term array.
- *
- * @return LSUP_OK on success; LSUP_MEM_ERR on allocation error.
- */
-LSUP_rc
-LSUP_pred_obj_list_add (LSUP_PredObjList *pol, LSUP_Term *p, LSUP_Term **o);
-
-
-/** @brief Add triples for a subject and a PO list to a graph.
- *
- * @param[in] it Graph iterator to use for insertion.
- *
- * @param[in] s Subject of all the triples.
- *
- * @param[in] po Predicate-object list.
- *
- * @return Number of triples parsed on success, or <0 (LSUP_*_ERR) on error.
- */
-size_t
-LSUP_spo_list_add_triples (
-        LSUP_GraphIterator *it, LSUP_Term *s, const LSUP_PredObjList *po);
-
-
-/** @brief Add triples for an anonymous collection to a graph.
- *
- * The `rdf:first`, `rdf:rest`, etc. terms are automatically added and the term
- * for the first item in the list is returned.
- *
- * @param[in] it Graph iterator to use for insertion.
- *
- * @param[in] ol NULL-terminated term array.
- *
- * @return Blank node representing the first list item.
- */
-LSUP_Term *
-LSUP_bnode_add_collection (LSUP_GraphIterator *it, LSUP_Term **ol);
-
 #endif

+ 33 - 0
include/graph.h

@@ -319,4 +319,37 @@ LSUP_graph_iter_graph (LSUP_GraphIterator *it);
 void
 LSUP_graph_iter_free (LSUP_GraphIterator *it);
 
+
+/** @brief Add triples for a term and related connection list to a graph.
+ *
+ * The connection list can be of inbound or outbound type; depending on that,
+ * triples are added with the given term as the subject, or the object.
+ *
+ * @param[in] it Graph iterator to use for insertion.
+ *
+ * @param[in] s Subject of all the triples.
+ *
+ * @param[in] po Predicate-object list.
+ *
+ * @return Number of triples parsed on success, or <0 (LSUP_*_ERR) on error.
+ */
+size_t
+LSUP_spo_list_add_triples (
+        LSUP_GraphIterator *it, LSUP_Term *s, const LSUP_ConnectionList *po);
+
+
+/** @brief Add triples for an anonymous collection to a graph.
+ *
+ * The `rdf:first`, `rdf:rest`, etc. terms are automatically added and the term
+ * for the first item in the list is returned.
+ *
+ * @param[in] it Graph iterator to use for insertion.
+ *
+ * @param[in] ol NUL-terminated term array.
+ *
+ * @return Blank node representing the first list item.
+ */
+LSUP_Term *
+LSUP_bnode_add_collection (LSUP_GraphIterator *it, LSUP_Term **ol);
+
 #endif

+ 91 - 0
include/term.h

@@ -100,6 +100,39 @@ typedef struct term_cache_entry_t {
 } LSUP_KeyedTerm;
 
 
+/// Connection type: inbound or outbound.
+typedef enum {
+    LSUP_CONN_INBOUND,              ///< Inbound connection.
+    LSUP_CONN_OUTBOUND,             ///< Outbound connection.
+} LSUP_ConnectionType;
+
+
+/** @brief Connection list.
+ *
+ * A list of predicates and related lists of terms, that can be used to list
+ * inbound or outbound connections to a node.
+ *
+ * Each term in the NUL-terminated `p` list represent a predicate which is
+ * paired with a list of terms in the `tl` list. The index of each predicate
+ * corresponds to the same index of a term list.
+ *
+ * If the type of the connection list is `LSUP_CONN_INBOUND`, the term list
+ * represent subjects and a term that is associated with the connection list is
+ * the related object; if `LSUP_CONN_OUTBOUND`, the term list represents
+ * objects, and a term that is associated with the connection list represents
+ * the subject.
+ *
+ */
+typedef struct {
+    LSUP_ConnectionType type;       ///< Inbound or outbound connection.
+    LSUP_Term **    p;              ///< NUL-terminated array of term handles.
+    LSUP_Term ***   tl;             /**<
+                                      * NUL-terminated array of
+                                      * NUL-terminated arrays of term handles.
+                                      */
+} LSUP_ConnectionList;
+
+
 /*
  * Extern variables.
  */
@@ -477,4 +510,62 @@ LSUP_tcache_add (const LSUP_Key key, const LSUP_Term *term);
 const LSUP_Term *
 LSUP_tcache_get (LSUP_Key key);
 
+
+/** @brief Add term to a term list.
+ *
+ * @param[in] tl Array of term handles to be added to. The handle must be NUL-
+ *  terminated. On success, this handle will be reallocated and the new address
+ *  returned, so the passed handle should no longer be used. On failure, it
+ *  remains unchanged and may be reused.
+ *
+ * @param[in] t Term to be added to the list. The object list will take
+ *  ownership of the term.
+ *
+ * @return Reallocated list on success; NULL on failure.
+ */
+LSUP_Term **
+LSUP_term_list_add (LSUP_Term **tl, LSUP_Term *t);
+
+
+/** @brief New predicate-object list.
+ *
+ * The initial state of the returned list is: `{p: [NULL], tl: [NULL]}`
+ *
+ * Predicates and term lists can be added with #LSUP_conn_list_add, and terms
+ * can be added to a term list with #LSUP_term_list_add.
+ *
+ * @return a new empty predicate-object list.
+ */
+LSUP_ConnectionList *
+LSUP_conn_list_list_new (LSUP_ConnectionType type);
+
+
+/** @brief Free a predicate-object list.
+ *
+ * All arrays and term handles are recursively freed.
+ *
+ * @param[in] pol Predicate-object list handle obtained with
+ *  #LSUP_conn_list_list_new().
+ */
+void
+LSUP_conn_list_list_free (LSUP_ConnectionList *pol);
+
+
+/** @brief Add a predicate-object list pair to a PO list.
+ *
+ * @param[in] pol Predicate-object list handle obtained with
+ *  #LSUP_conn_list_list_new().
+ *
+ *  @param[in] p Predicate to be associated with the given object list. The
+ *   PO structure takes ownership of the term.
+ *
+ *  @param[in] o NULL-terminated array of object term handles to be associated
+ *   with the given predicate. The PO structire takes ownership of the whole
+ *   term array.
+ *
+ * @return LSUP_OK on success; LSUP_MEM_ERR on allocation error.
+ */
+LSUP_rc
+LSUP_conn_list_list_add (LSUP_ConnectionList *pol, LSUP_Term *p, LSUP_Term **o);
+
 #endif

+ 0 - 157
src/codec.c

@@ -69,163 +69,6 @@ uint8_t *unescape_unicode (const uint8_t *esc_str, size_t size)
 }
 
 
-LSUP_Term **
-LSUP_obj_list_add (LSUP_Term **ol, LSUP_Term *o)
-{
-    size_t i = 0;
-    while (ol[i++]); // Count includes sentinel.
-    LSUP_Term **ret = realloc (ol, sizeof (*ol) * (i + 1));
-    if (!ret) return NULL;
-
-    ret[i - 1] = o;
-    ret[i] = NULL;
-
-    return ret;
-}
-
-
-LSUP_PredObjList *
-LSUP_pred_obj_list_new (void)
-{
-    /*
-     * Init state:
-     * {p: [NULL], o: [NULL]}
-     */
-    LSUP_PredObjList *po;
-    MALLOC_GUARD (po, NULL);
-    // Set sentinels.
-    CALLOC_GUARD (po->p, NULL);
-    CALLOC_GUARD (po->o, NULL);
-
-    return po;
-}
-
-
-void
-LSUP_pred_obj_list_free (LSUP_PredObjList *po)
-{
-    log_debug ("Freeing predicate object list.");
-    for (size_t i = 0; po->p[i]; i++) {
-        // Free individual predicate handles.
-        LSUP_term_free (po->p[i]);
-    }
-    // Free pred list.
-    free (po->p);
-
-    for (size_t i = 0; po->o[i]; i++) {
-        for (size_t j = 0; po->o[i][j]; j++) {
-            // Free individual term handles.
-            LSUP_term_free (po->o[i][j]);
-        }
-        // Free object list.
-        free (po->o[i]);
-    }
-    // Free list of object lists.
-    free (po->o);
-
-    free (po);
-}
-
-
-LSUP_rc
-LSUP_pred_obj_list_add (LSUP_PredObjList *po, LSUP_Term *p, LSUP_Term **o)
-{
-    size_t i;
-
-    i = 0;
-    while (po->p[i++]);  // Count includes sentinel.
-    LSUP_Term **tmp_p = realloc (po->p, sizeof (*po->p) * (i + 1));
-    if (!tmp_p) return LSUP_MEM_ERR;
-    tmp_p[i - 1] = p;
-    tmp_p[i] = NULL;
-    po->p = tmp_p;
-
-    i = 0;
-    while (po->o[i++]);
-    LSUP_Term ***tmp_o = realloc (po->o, sizeof (*po->o) * (i + 1));
-    if (!tmp_o) return LSUP_MEM_ERR;
-    tmp_o[i - 1] = o;
-    tmp_o[i] = NULL;
-    po->o = tmp_o;
-
-    return LSUP_OK;
-}
-
-
-size_t
-LSUP_spo_list_add_triples (
-        LSUP_GraphIterator *it, LSUP_Term *s, const LSUP_PredObjList *po)
-{
-    size_t ct = 0;
-    if (!s) {
-        log_error ("Subject is NULL!");
-        return LSUP_VALUE_ERR;
-    }
-    if (!po->p) {
-        log_error ("Predicate is NULL!");
-        return LSUP_VALUE_ERR;
-    }
-    if (!po->o) {
-        log_error ("Object list is NULL!");
-        return LSUP_VALUE_ERR;
-    }
-    LSUP_Triple *spo = LSUP_triple_new (s, NULL, NULL);
-    for (size_t i = 0; po->p[i]; i++) {
-        spo->p = po->p[i];
-        for (size_t j = 0; po->o[i][j]; j++) {
-            spo->o = po->o[i][j];
-
-            LSUP_rc rc = LSUP_graph_add_iter (it, spo);
-            if (rc >= 0) ct++;
-            PRCCK (rc);
-        }
-    }
-    free (spo);
-
-    return ct;
-}
-
-
-LSUP_Term *
-LSUP_bnode_add_collection (LSUP_GraphIterator *it, LSUP_Term **ol)
-{
-    LSUP_NSMap *nsm = LSUP_graph_namespace (LSUP_graph_iter_graph (it));
-    LSUP_Term
-        *s = LSUP_term_new (LSUP_TERM_BNODE, NULL, NULL),
-        *rdf_first = LSUP_iriref_new ("rdf:first", nsm),
-        *rdf_rest = LSUP_iriref_new ("rdf:rest", nsm),
-        *rdf_nil = LSUP_iriref_new ("rdf:nil", nsm),
-        *link;
-
-    LSUP_Triple *spo = TRP_DUMMY;
-    link = s;
-    for (size_t i = 0; ol[i]; i++) {
-        spo->s = link;
-        spo->p = rdf_first;
-        spo->o = ol[i];
-        PRCNL (LSUP_graph_add_iter (it, spo));
-
-        spo->p = rdf_rest;
-        spo->o = (
-                ol[i + 1] ? LSUP_term_new (LSUP_TERM_BNODE, NULL, NULL)
-                : rdf_nil);
-
-        PRCNL (LSUP_graph_add_iter (it, spo));
-
-        if (link != s) LSUP_term_free (link);
-        // Current object becomes next subject. Irrelevant for last item.
-        link = spo->o;
-    }
-
-    LSUP_term_free (rdf_first);
-    LSUP_term_free (rdf_rest);
-    LSUP_term_free (rdf_nil);
-    free (spo);
-
-    return s;
-}
-
-
 /*
  * Extern inline functions.
  */

+ 10 - 10
src/codec/grammar_ttl.y

@@ -85,7 +85,7 @@ triples 	::= subject(S) ows predObjList(L) PERIOD . {
                 log_trace ("Added %lu triples.", ct);
 
                 LSUP_term_free (S);
-                LSUP_pred_obj_list_free (L);
+                LSUP_conn_list_list_free (L);
             }
 triples 	::= subject(S) ows predObjList(L) SEMICOLON PERIOD . [PERIOD] {
                 size_t ct = LSUP_spo_list_add_triples (state->it, S, L);
@@ -94,17 +94,17 @@ triples 	::= subject(S) ows predObjList(L) SEMICOLON PERIOD . [PERIOD] {
                 log_trace ("Added %lu triples.", ct);
 
                 LSUP_term_free (S);
-                LSUP_pred_obj_list_free (L);
+                LSUP_conn_list_list_free (L);
             }
 
-%type predObjList       { LSUP_PredObjList * }
-%destructor predObjList { LSUP_pred_obj_list_free ($$); }
+%type predObjList       { LSUP_ConnectionList * }
+%destructor predObjList { LSUP_conn_list_list_free ($$); }
 predObjList(A) ::= predicate(P) ows objectList(O) . [SEMICOLON] {
-                A = LSUP_pred_obj_list_new();
-                LSUP_pred_obj_list_add (A, P, O);
+                A = LSUP_conn_list_list_new(LSUP_CONN_OUTBOUND);
+                LSUP_conn_list_list_add (A, P, O);
             }
 predObjList(A) ::= predObjList(L) SEMICOLON predicate(P) ows objectList(O) . {
-                LSUP_pred_obj_list_add (L, P, O);
+                LSUP_conn_list_list_add (L, P, O);
                 A = L;
             }
 
@@ -116,7 +116,7 @@ predObjList(A) ::= predObjList(L) SEMICOLON predicate(P) ows objectList(O) . {
     free ($$);
 }
 objectList(A) ::= objectList(L) COMMA object(O) . {
-                A = LSUP_obj_list_add (L, O);
+                A = LSUP_term_list_add (L, O);
             }
 objectList(A) ::= object(O) . [IRIREF] {
                 A = calloc (sizeof (*A), 2);
@@ -222,7 +222,7 @@ blank(A)    ::= LBRACKET predObjList(L) RBRACKET . [BNODE_ID] {
                 state->ct += LSUP_spo_list_add_triples (state->it, A, L);
                 log_trace ("Created list BN: _:%s", A->data);
 
-                LSUP_pred_obj_list_free (L);
+                LSUP_conn_list_list_free (L);
             }
 blank       ::= collection . [BNODE_ID]
 blank(A)    ::= LPAREN RPAREN . [BNODE_ID] {
@@ -252,7 +252,7 @@ collection(A) ::= LPAREN itemList(L) RPAREN . {
     while ($$[i]) LSUP_term_free ($$[i++]);
     free ($$);
 }
-itemList(A) ::= itemList(L) ows object(O) . { A = LSUP_obj_list_add (L, O); }
+itemList(A) ::= itemList(L) ows object(O) . { A = LSUP_term_list_add (L, O); }
 itemList(A) ::= object(O) . {
                 A = calloc (sizeof (*A), 2);
                 A[0] = O;

+ 82 - 0
src/graph.c

@@ -501,6 +501,88 @@ LSUP_graph_abort (LSUP_Graph *gr)
 }
 
 
+size_t
+LSUP_spo_list_add_triples (
+        LSUP_GraphIterator *it, LSUP_Term *t, const LSUP_ConnectionList *cl)
+{
+    size_t ct = 0;
+    if (!t) {
+        log_error ("Related term is NULL!");
+        return LSUP_VALUE_ERR;
+    }
+    if (!cl->p) {
+        log_error ("Predicate is NULL!");
+        return LSUP_VALUE_ERR;
+    }
+    if (!cl->tl) {
+        log_error ("Term list is NULL!");
+        return LSUP_VALUE_ERR;
+    }
+
+    LSUP_Triple *spo = LSUP_triple_new (NULL, NULL, NULL);
+    if (cl->type == LSUP_CONN_INBOUND)
+        spo->o = t;
+    else spo->s = t;
+
+    for (size_t i = 0; cl->p[i]; i++) {
+        spo->p = cl->p[i];
+        for (size_t j = 0; cl->tl[i][j]; j++) {
+            if (cl->type == LSUP_CONN_INBOUND)
+                spo->s = cl->tl[i][j];
+            else
+                spo->o = cl->tl[i][j];
+
+            LSUP_rc rc = LSUP_graph_add_iter (it, spo);
+            if (rc >= 0) ct++;
+            PRCCK (rc);
+        }
+    }
+    free (spo);
+
+    return ct;
+}
+
+
+LSUP_Term *
+LSUP_bnode_add_collection (LSUP_GraphIterator *it, LSUP_Term **ol)
+{
+    LSUP_NSMap *nsm = LSUP_graph_namespace (LSUP_graph_iter_graph (it));
+    LSUP_Term
+        *s = LSUP_term_new (LSUP_TERM_BNODE, NULL, NULL),
+        *rdf_first = LSUP_iriref_new ("rdf:first", nsm),
+        *rdf_rest = LSUP_iriref_new ("rdf:rest", nsm),
+        *rdf_nil = LSUP_iriref_new ("rdf:nil", nsm),
+        *link;
+
+    LSUP_Triple *spo = TRP_DUMMY;
+    link = s;
+    for (size_t i = 0; ol[i]; i++) {
+        spo->s = link;
+        spo->p = rdf_first;
+        spo->o = ol[i];
+        PRCNL (LSUP_graph_add_iter (it, spo));
+
+        spo->p = rdf_rest;
+        spo->o = (
+                ol[i + 1] ? LSUP_term_new (LSUP_TERM_BNODE, NULL, NULL)
+                : rdf_nil);
+
+        PRCNL (LSUP_graph_add_iter (it, spo));
+
+        if (link != s) LSUP_term_free (link);
+        // Current object becomes next subject. Irrelevant for last item.
+        link = spo->o;
+    }
+
+    LSUP_term_free (rdf_first);
+    LSUP_term_free (rdf_rest);
+    LSUP_term_free (rdf_nil);
+    free (spo);
+
+    return s;
+}
+
+
 /*
  * Static functions.
  */

+ 84 - 0
src/term.c

@@ -457,6 +457,90 @@ LSUP_tcache_get (LSUP_Key key)
 }
 
 
+/*
+ * Multi-add functions.
+ */
+
+LSUP_Term **
+LSUP_term_list_add (LSUP_Term **tl, LSUP_Term *t)
+{
+    size_t i = 0;
+    while (tl[i++]); // Count includes sentinel.
+    LSUP_Term **ret = realloc (tl, sizeof (*tl) * (i + 1));
+    if (!ret) return NULL;
+
+    ret[i - 1] = t;
+    ret[i] = NULL;
+
+    return ret;
+}
+
+
+LSUP_ConnectionList *
+LSUP_conn_list_list_new (LSUP_ConnectionType type)
+{
+    LSUP_ConnectionList *cl;
+    MALLOC_GUARD (cl, NULL);
+    cl->type = type;
+    // Set sentinels.
+    CALLOC_GUARD (cl->p, NULL);
+    CALLOC_GUARD (cl->tl, NULL);
+
+    return cl;
+}
+
+
+void
+LSUP_conn_list_list_free (LSUP_ConnectionList *cl)
+{
+    log_debug ("Freeing predicate object list.");
+    for (size_t i = 0; cl->p[i]; i++) {
+        // Free individual predicate handles.
+        LSUP_term_free (cl->p[i]);
+    }
+    // Free pred list.
+    free (cl->p);
+
+    for (size_t i = 0; cl->tl[i]; i++) {
+        for (size_t j = 0; cl->tl[i][j]; j++) {
+            // Free individual term handles.
+            LSUP_term_free (cl->tl[i][j]);
+        }
+        // Free object list.
+        free (cl->tl[i]);
+    }
+    // Free list of object lists.
+    free (cl->tl);
+
+    free (cl);
+}
+
+
+LSUP_rc
+LSUP_conn_list_list_add (LSUP_ConnectionList *cl, LSUP_Term *p, LSUP_Term **tl)
+{
+    size_t i;
+
+    i = 0;
+    while (cl->p[i++]);  // Count includes sentinel.
+    LSUP_Term **tmp_p = realloc (cl->p, sizeof (*cl->p) * (i + 1));
+    if (!tmp_p) return LSUP_MEM_ERR;
+    tmp_p[i - 1] = p;
+    tmp_p[i] = NULL;
+    cl->p = tmp_p;
+
+    i = 0;
+    while (cl->tl[i++]);
+    LSUP_Term ***tmp_tl = realloc (cl->tl, sizeof (*cl->tl) * (i + 1));
+    if (!tmp_tl) return LSUP_MEM_ERR;
+    tmp_tl[i - 1] = tl;
+    tmp_tl[i] = NULL;
+    cl->tl = tmp_tl;
+
+    return LSUP_OK;
+}
+
+
 /*
  * Static functions.
  */