Browse Source

WIP add link maps.

scossu 3 days ago
parent
commit
465e63204c
7 changed files with 190 additions and 81 deletions
  1. 3 3
      include/graph.h
  2. 1 1
      include/namespace.h
  3. 23 28
      include/store_interface.h
  4. 28 32
      include/term.h
  5. 121 3
      lua/src/graph.c
  6. 12 13
      src/term.c
  7. 2 1
      test/test_graph.c

+ 3 - 3
include/graph.h

@@ -466,9 +466,9 @@ LSUP_TermSet *
 LSUP_graph_unique_terms (const LSUP_Graph *gr, LSUP_TriplePos pos);
 
 
-/** @brief Add triples for a term and related connection list to a graph.
+/** @brief Add triples for a term and related link map to a graph.
  *
- * The connection list can be of inbound, outbound, or edge type; depending on
+ * The link map can be of inbound, outbound, or edge type; depending on
  * that, triples are added with the given term as the subject, the predicate,
  * or the object.
  *
@@ -476,7 +476,7 @@ LSUP_graph_unique_terms (const LSUP_Graph *gr, LSUP_TriplePos pos);
  *
  * @param[in] t Term to be associated with the collection list.
  *
- * @param[in] cl Link map.
+ * @param[in] lm Link map.
  *
  * @return Number of triples parsed on success, or <0 (LSUP_*_ERR) on error.
  */

+ 1 - 1
include/namespace.h

@@ -20,7 +20,7 @@
  *
  * It contains a double hash map of pfx->ns and ns->pfx for fast 2-way lookup.
  *
- * @FIXME that's not true, currently ns lookup by prefix involves an iteration.
+ * FIXME that's not true, currently ns lookup by prefix involves an iteration.
  *
  * Prefixes are fixed PFX_LEN-size strings, namespaces are arbitrary sized
  * strings.

+ 23 - 28
include/store_interface.h

@@ -485,27 +485,24 @@ typedef struct store_if_t {
     iter_txn_fn_t       iter_txn_fn;    ///< Get iterator's transaction.
 
     //Context setting.
-    store_update_ctx_fn_t update_ctx_fn; /**< Update context URI.
-                                         *
-                                         *   Only available in stores with
-                                         *   #LSUP_STORE_CTX feature. Optional.
-                                         */
+    store_update_ctx_fn_t update_ctx_fn; ///< Update context URI.
+                                         ///<
+                                         ///< Only available in stores with
+                                         ///< #LSUP_STORE_CTX feature. Optional.
 
     // Addition.
     store_add_init_fn_t add_init_fn;    ///< Initialize add iteration.
     store_add_iter_fn_t add_iter_fn;    ///< Add one triple.
-    store_add_abort_fn_t add_abort_fn;  /**< Abort (roll back) the add process.
-                                         *
-                                         *   Only available in
-                                         *   stores with #LSUP_STORE_TXN
-                                         *   feature. Optional.
-                                         */
+    store_add_abort_fn_t add_abort_fn;  ///< Abort (roll back) the add process.
+                                        ///<
+                                        ///< Only available in
+                                        ///< stores with #LSUP_STORE_TXN
+                                        ///< feature. Optional.
     store_add_done_fn_t add_done_fn;    ///< Complete the add process.
-    store_add_term_fn_t add_term_fn;    /**< Add (index) a term to the store.
-                                         *
-                                         *   Only available in stores with
-                                         *   #LSUP_STORE_IDX feature. Optional.
-                                         */
+    store_add_term_fn_t add_term_fn;    ///< Add (index) a term to the store.
+                                        ///<
+                                        ///< Only available in stores with
+                                        ///< #LSUP_STORE_IDX feature. Optional.
 
     // Look up.
     store_lookup_fn_t   lookup_fn;      ///< Look up triples by pattern. 
@@ -517,18 +514,16 @@ typedef struct store_if_t {
     store_remove_fn_t   remove_fn;      ///< Remove triples by pattern.
 
     // Namespace prefix mapping.
-    store_nsm_put_fn_t  nsm_put_fn;     /**< Add a ns/pfx pair to the map.
-                                         *
-                                         *  Only available (and mandatory)
-                                         *  in stores with the
-                                         *  #LSUP_STORE_IDX feature.
-                                         */
-    store_nsm_get_fn_t  nsm_get_fn;     /**< Get a namespace from the map.
-                                         *
-                                         *  Only available (and mandatory)
-                                         *  in stores with the
-                                         *  #LSUP_STORE_IDX feature.
-                                         */
+    store_nsm_put_fn_t  nsm_put_fn;     ///< Add a ns/pfx pair to the map.
+                                        ///<
+                                        ///< Only available (and mandatory)
+                                        ///< in stores with the
+                                        ///< #LSUP_STORE_IDX feature.
+    store_nsm_get_fn_t  nsm_get_fn;     ///< Get a namespace from the map.
+                                        ///<
+                                        ///< Only available (and mandatory)
+                                        ///< in stores with the
+                                        ///< #LSUP_STORE_IDX feature.
 } LSUP_StoreInt;
 
 

+ 28 - 32
include/term.h

@@ -30,10 +30,9 @@ typedef char LSUP_LangTag[8];
 
 /// Term type.
 typedef enum {
-    LSUP_TERM_UNDEFINED = 0,/**<
-                              * Undefined placeholder or result of an error.
-                              * Invalid for most operations.
-                              */
+    LSUP_TERM_UNDEFINED = 0,///< Undefined placeholder or result of an error.
+                            ///<
+                            ///< Invalid for most operations.
     LSUP_TERM_IRIREF,       ///< IRI reference.
     LSUP_TERM_NS_IRIREF,    ///< Namespace-prefixed IRI reference.
     LSUP_TERM_LITERAL,      ///< Literal without language tag.
@@ -49,14 +48,14 @@ typedef struct link_map_iter LSUP_LinkMapIterator;
 
 /// RDF term.
 typedef struct term_t {
-    char *              data;       // URI, literal value, or BNode label.
+    char *              data;       ///< URI, literal value, or BNode label.
     union {
-        struct term_t * datatype;   // Data type IRI for LSUP_TERM_LITERAL.
-        LSUP_LangTag    lang;       // Lang tag for LSUP_TERM_LT_LITERAL.
-        LSUP_Key        bnode_id;   // BNode ID for comparison & skolemization.
-        LSUP_IRIInfo *  iri_info;   // IRI information structure.
+        struct term_t * datatype;   ///< Data type IRI for LSUP_TERM_LITERAL.
+        LSUP_LangTag    lang;       ///< Lang tag for LSUP_TERM_LT_LITERAL.
+        LSUP_Key        bnode_id;   ///< BNode ID for comparison & skolemization.
+        LSUP_IRIInfo *  iri_info;   ///< IRI information structure.
     };
-    LSUP_TermType       type;       // Term type.
+    LSUP_TermType       type;       ///< Term type.
 } LSUP_Term;
 
 
@@ -105,11 +104,13 @@ typedef enum {
  *
  * If the type of the link map is `LSUP_LINK_INBOUND`, the map keys
  * represent predicates and the sets related to them are the objects, and the
- * term associated to the link map is the object; if
- * `LSUP_LINK_OUTBOUND`, the keys represent predicates, the related sets
- * objects, and the associated term is the subject. If `LSUP_LINK_EDGE`, the
- * keys represent subjects and the related sets objects, and the associated
- * term is the predicate.
+ * term associated to the link map is the object.
+ *
+ * If the type is `LSUP_LINK_OUTBOUND`, the keys represent predicates, the
+ * related sets objects, and the associated term is the subject.
+ *
+ * If the type is `LSUP_LINK_EDGE`, the keys represent subjects and the related
+ * sets objects, and the associated term is the predicate.
  */
 typedef struct link_map LSUP_LinkMap;
 
@@ -550,14 +551,12 @@ LSUP_term_set_next (LSUP_TermSet *ts, size_t *i, LSUP_Term **term);
 
 /** @brief New link map.
  *
- * The initial state of the returned list is: `{t: [NULL], tl: [NULL]}`
- *
- * Terms can be added to a term list with #LSUP_term_set_add().
+ * Terms can be added to a link map with #LSUP_term_set_add().
  *
  * @param[in] type Type of links that the link map shall contain.
  * @sa #LSUP_LinkType
  *
- * @return a new empty predicate-object list.
+ * @return a new empty link map.
  */
 LSUP_LinkMap *
 LSUP_link_map_new (LSUP_LinkType type);
@@ -567,10 +566,10 @@ LSUP_link_map_new (LSUP_LinkType type);
  *
  * All arrays and term handles are recursively freed.
  *
- * @param[in] pol link map handle obtained with #LSUP_link_map_new().
+ * @param[in] lm link map handle obtained with #LSUP_link_map_new().
  */
 void
-LSUP_link_map_free (LSUP_LinkMap *pol);
+LSUP_link_map_free (LSUP_LinkMap *lm);
 
 
 /** @brief Return the link map type.
@@ -590,7 +589,7 @@ LSUP_link_map_type (const LSUP_LinkMap *map);
  * In any case, the caller should not directly use the term and term set after
  * passing them to this function.
  *
- * @param[in] cmap Link map handle obtained with #LSUP_link_map_new().
+ * @param[in] lmap Link map handle obtained with #LSUP_link_map_new().
  *
  * @param[in] term Term to be associated with the given object list. The
  *  link map structure takes ownership of the term.
@@ -602,24 +601,17 @@ LSUP_link_map_type (const LSUP_LinkMap *map);
  */
 LSUP_rc
 LSUP_link_map_add (
-        LSUP_LinkMap *cmap, LSUP_Term *term, LSUP_TermSet *tset);
+        LSUP_LinkMap *lmap, LSUP_Term *term, LSUP_TermSet *tset);
 
 
 /** @brief Create a new iterator to loop through a link map.
  *
  * @param[in] lmap Map handle to iterate.
- *
- * @param[in] ext External term to look for connections.
  */
 LSUP_LinkMapIterator *
 LSUP_link_map_iter_new (const LSUP_LinkMap *lmap, LSUP_Term *ext);
 
 
-/// Free a link map iterator.
-void
-LSUP_link_map_iter_free (LSUP_LinkMapIterator *it);
-
-
 /** @brief Iterate through a link map.
  *
  * Each call to this function yields a linked term and the related term set.
@@ -638,6 +630,11 @@ LSUP_link_map_next (
         LSUP_LinkMapIterator *it, LSUP_Term **lt, LSUP_TermSet **ts);
 
 
+/// Free a link map iterator.
+void
+LSUP_link_map_iter_free (LSUP_LinkMapIterator *it);
+
+
 /**@brief Iterate over a link map and generate triples.
  *
  * Calling this function repeatedly builds triples for all the linked terms and
@@ -655,8 +652,7 @@ LSUP_link_map_next (
  *  has been reached; <0 on error.
  */
 LSUP_rc
-LSUP_link_map_triples (
-        LSUP_LinkMapIterator *it, LSUP_Triple *spo);
+LSUP_link_map_triples (LSUP_LinkMapIterator *it, LSUP_Triple *spo);
 
 ///@} END defgroup term
 #endif

+ 121 - 3
lua/src/graph.c

@@ -166,7 +166,7 @@ static int l_graph_add (lua_State *L)
 }
 
 
-static int l_graph_iter_next (lua_State *L)
+static int graph_iter_next (lua_State *L)
 {
     LSUP_GraphIterator *it =
         *(LSUP_GraphIterator **)lua_touserdata (L, lua_upvalueindex (1));
@@ -178,7 +178,6 @@ static int l_graph_iter_next (lua_State *L)
     LSUP_rc rc = LSUP_graph_iter_next (it, spo_p);
 
     if (rc == LSUP_END) {
-        LSUP_graph_iter_free (it);
         lua_pushnil (L);
         lua_pushstring (L, "End of lookup results.");
         return 2;
@@ -211,20 +210,116 @@ static int l_graph_lookup (lua_State *L)
     LUA_NLCHECK (*it_p, "Error creating graph iterator.");
     LOG_DEBUG ("Found triples: %d", ct);
 
-    lua_pushcclosure (L, l_graph_iter_next, 1);
+    lua_pushcclosure (L, graph_iter_next, 1);
 
     return 1;
 }
 
 
+static int graph_iter_gc (lua_State *L)
+{
+    LSUP_GraphIterator *it = *(LSUP_GraphIterator **)lua_touserdata (L, 1);
+    LSUP_graph_iter_free (it);
+}
+
+
+static int conn_iter_done (lua_State *L)
+{
+    LSUP_LinkMapIterator *it =
+        *(LSUP_LinkMapIterator **)lua_touserdata (L, lua_upvalueindex (1));
+    LSUP_link_map_iter_free (it);
+
+    return 0;
+}
+
+
+static int lmap_iter_next (lua_State *L)
+{
+    LSUP_LinkMapIterator *it =
+        *(LSUP_LinkMapIterator **)lua_touserdata (L, lua_upvalueindex (1));
+
+    LSUP_Term **link_p = (LSUP_Term **)lua_newuserdata (L, sizeof *link_p);
+    *link_p = NULL;
+    LSUP_TermSet *ts = NULL;
+    LSUP_rc rc = LSUP_link_map_next (it, link_p, &ts);
+
+    if (rc != LSUP_OK) {
+        if (rc == LSUP_END) {
+            LSUP_link_map_iter_free (it);
+            lua_pushnil (L);
+            lua_pushstring (L, "End of the loop.");
+            return 2;
+        }
+        else LUA_PCHECK (rc, "Error iterating through link map");
+    }
+
+    size_t i = 0;
+    LSUP_Term *conn = NULL;
+    lua_newtable (L);
+    while (LSUP_term_set_next (ts, &i, &conn)) {
+        LSUP_Term **conn_p = (LSUP_Term **)lua_newuserdata (L, sizeof *conn_p);
+        *conn_p = conn;
+        lua_pushboolean (L, true);
+        lua_rawset (L, -3);
+    }
+
+    return 2;
+}
+
+
+static int l_lmap_iter_init (lua_State *L)
+{
+    LSUP_LinkMap *lm = *(LSUP_LinkMap **)luaL_checkudata(L, 1, "LSUP.LinkMap");
+
+    LSUP_LinkMapIterator **lmit_p =
+        (LSUP_LinkMapIterator  **)lua_newuserdata (L, sizeof *lmit_p);
+    *lmit_p = LSUP_link_map_iter_new (lm);
+    luaL_getmetatable (L, "LSUP.LMapIterator");
+    lua_setmetatable (L, -2);
+    stackDump (L, "After allocating LMIter");
+
+    lua_pushcclosure (L, lmap_iter_next, 1);
+
+    return 1;
+}
+
+
+/** Returns a LinkMap that can be iterated over with iter().
+ */
 static int l_graph_connections (lua_State *L)
 {
     const LSUP_Graph *gr = check_graph (L);
+    LSUP_Term *t = *(LSUP_Term **)luaL_checkudata (L, 2, "LSUP.Term");
+    const LSUP_LinkType type = luaL_checkinteger (L, 3);
+
+    LSUP_LinkMap **lm_p =
+        (LSUP_LinkMap **)lua_newuserdata (L, sizeof *lm_p);
+    *lm_p = LSUP_graph_connections (gr, t, type);
+    luaL_getmetatable (L, "LSUP.LinkMap");
+    lua_setmetatable (L, -2);
 
     return 1;
 }
 
 
+static int link_map_gc (lua_State *L)
+{
+    LSUP_LinkMap *lm = *(LSUP_LinkMap **)lua_touserdata (L, 1);
+    LSUP_link_map_free (lm);
+
+    return 0;
+}
+
+
+static int lmap_iter_gc (lua_State *L)
+{
+    LSUP_LinkMapIterator *it = *(LSUP_LinkMapIterator **)lua_touserdata (L, 1);
+    LSUP_link_map_iter_free (it);
+
+    return 0;
+}
+
+
 static int l_graph_term_set (lua_State *L)
 {
     const LSUP_Graph *gr = check_graph (L);
@@ -293,6 +388,15 @@ static const luaL_Reg graph_lib_meth [] = {
 };
 
 
+static const LEnumConst graph_enums[] = {
+    {"LINK_INBOUND", LSUP_LINK_INBOUND},
+    {"LINK_OUTBOUND", LSUP_LINK_OUTBOUND},
+    {"LINK_EDGE", LSUP_LINK_EDGE},
+
+    {NULL, 0}
+};
+
+
 int luaopen_lsup_graph (lua_State *L)
 {
     LSUP_init();  // This is idempotent: no problem calling it multiple times.
@@ -301,7 +405,18 @@ int luaopen_lsup_graph (lua_State *L)
     lua_setfield (L, -2, "__index");
     luaL_setfuncs (L, graph_lib_meth, 0);
 
+    // Metatables for ancillary types.
     luaL_newmetatable (L, "LSUP.GraphIterator");
+    lua_pushcfunction (L, graph_iter_gc);
+    lua_setfield (L, -2, "__gc");
+
+    luaL_newmetatable (L, "LSUP.LinkMap");
+    lua_pushcfunction (L, link_map_gc);
+    lua_setfield (L, -2, "__gc");
+
+    luaL_newmetatable (L, "LSUP.LMapIterator");
+    lua_pushcfunction (L, lmap_iter_gc);
+    lua_setfield (L, -2, "__gc");
 
     /*
     // Getters table.
@@ -315,5 +430,8 @@ int luaopen_lsup_graph (lua_State *L)
     */
     luaL_newlib (L, graph_lib_fn);
 
+    // Module-level constants.
+    push_int_const (L, graph_enums);
+
     return 1;
 }

+ 12 - 13
src/term.c

@@ -605,22 +605,22 @@ LSUP_term_set_free (LSUP_TermSet *ts)
 LSUP_LinkMap *
 LSUP_link_map_new (LSUP_LinkType type)
 {
-    LSUP_LinkMap *cm;
-    MALLOC_GUARD (cm, NULL);
-    cm->type = type;
-    cm->links = hashmap_new (
+    LSUP_LinkMap *lm;
+    MALLOC_GUARD (lm, NULL);
+    lm->type = type;
+    lm->links = hashmap_new (
             sizeof (Link), 0, LSUP_HASH_SEED, 0,
             link_map_hash_fn, link_map_cmp_fn, link_map_free_fn, NULL);
 
-    return cm;
+    return lm;
 }
 
 
 void
-LSUP_link_map_free (LSUP_LinkMap *cm)
+LSUP_link_map_free (LSUP_LinkMap *lm)
 {
-    hashmap_free (cm->links);
-    free (cm);
+    hashmap_free (lm->links);
+    free (lm);
 }
 
 
@@ -632,12 +632,12 @@ LSUP_link_map_type (const LSUP_LinkMap *map)
 // TODO Memory error handling.
 LSUP_rc
 LSUP_link_map_add (
-        LSUP_LinkMap *cmap, LSUP_Term *term, LSUP_TermSet *tset)
+        LSUP_LinkMap *lmap, LSUP_Term *term, LSUP_TermSet *tset)
 {
     // Keyed term to look up the link term and insert it, if necessary.
     KeyedTerm entry_s = {.key=LSUP_term_hash (term), .term=term};
 
-    Link *ex = hashmap_get (cmap->links, &(Link){.term=&entry_s});
+    Link *ex = hashmap_get (lmap->links, &(Link){.term=&entry_s});
     if (ex) {
         // Add terms one by one to the existing term set.
         LOG_TRACE(
@@ -666,7 +666,7 @@ LSUP_link_map_add (
         MALLOC_GUARD (ins, LSUP_MEM_ERR);
         memcpy (ins, &entry_s, sizeof (entry_s));
         Link link = {.term=ins, .tset=tset};
-        hashmap_set (cmap->links, &link);
+        hashmap_set (lmap->links, &link);
     }
 
     return LSUP_OK;
@@ -686,8 +686,7 @@ LSUP_link_map_iter_new (const LSUP_LinkMap *lmap, LSUP_Term *ext)
 
 
 void
-LSUP_link_map_iter_free (LSUP_LinkMapIterator *it)
-{ free (it); }
+LSUP_link_map_iter_free (LSUP_LinkMapIterator *it) { free (it); }
 
 
 LSUP_rc

+ 2 - 1
test/test_graph.c

@@ -50,7 +50,7 @@ _graph_add (LSUP_StoreType type)
     LSUP_Graph *gr;
     LSUP_Store *store;
 
-    if (type = LSUP_STORE_HTABLE) store = NULL;
+    if (type == LSUP_STORE_HTABLE) store = NULL;
     else store = LSUP_store_new (type, NULL, 0);
 
     gr = LSUP_graph_new (store, NULL, NULL);
@@ -84,6 +84,7 @@ _graph_add (LSUP_StoreType type)
     ASSERT (!LSUP_graph_equals (gr2, gr), "Graphs should not be equal!");
 
     LSUP_graph_free (gr);
+    LSUP_graph_free (gr2);
     if (type != LSUP_STORE_HTABLE) LSUP_store_free (store);
 
     return 0;