Procházet zdrojové kódy

Namespace overhaul:

* Remove the `LSUP_TERM_NS_IRIREF` type. All IRIrefs are stored
  in their full form.
* Add `LSUP_iriref_new_ns()` and `LSUP_graph_new_ns()` to explicit pass
  a ns-prefixed URI string.
* Change behavior of `LSUP_nsmap_normalize_uri` so that it fails if the
  passed string is not in a prefixed format, or if the prefix is not in
  the NS map, rather than creating a copy of the original string.  This
  implies that the client must know if the string URI is in a prefixed
  format (i.e.  no blanket normalization), and it's necessary to prevent
  undetected creation of malformed URIs.
* Use only one global namespace map, `LSUP_default_nsm`. Multiple NSMs
  are of little use and created unnecessary complexity.
* Adjust function signatures and tests to reflect the switch to one NSM.
scossu před 1 dnem
rodič
revize
b6ff36ae93

+ 2 - 7
include/lsup/codec.h

@@ -23,7 +23,6 @@ typedef struct codec_t LSUP_Codec;
 /// Parser state.
 typedef struct ttl_parser_state {
     LSUP_GraphIterator *    it;     ///< Iterator used to build the graph.
-    LSUP_NSMap *            nsm;    ///< NS map used in the document.
     LSUP_Term *             base;   ///< Base IRI used in the document.
     LSUP_Term *             lms;    ///< Link map subject.
     size_t                  ct;     ///< Statements parsed.
@@ -50,8 +49,6 @@ typedef struct parse_error_t {
  *
  * @param[in] term Single term handle.
  *
- * @param[in] nsm Namespace map. May be NULL for no prefix shortening.
- *
  * @param[out] rep Pointer to a string to be filled with the encoded term. The
  *  string is reallocated and, if reused for multiple calls to this function,
  *  it only needs to be freed after the last call. It should be initialized to
@@ -59,8 +56,7 @@ typedef struct parse_error_t {
  *
  * @return LSUP_OK on successful encoding; <0 for other errors.
  */
-typedef LSUP_rc (*term_enc_fn_t)(
-        const LSUP_Term *term, const LSUP_NSMap *nsm, char **rep);
+typedef LSUP_rc (*term_enc_fn_t)(const LSUP_Term *term, char **rep);
 
 
 /** @brief Initialize a graph encoding loop.
@@ -128,8 +124,7 @@ typedef void (*gr_encode_done_fn_t)(void *it);
  * @return Implementations MUST return LSUP_OK on success and a negative value
  *  on parsing error.
  */
-typedef LSUP_rc (*term_decode_fn_t)(
-        const char *rep, const LSUP_NSMap *nsm, LSUP_Term **term);
+typedef LSUP_rc (*term_decode_fn_t)(const char *rep, LSUP_Term **term);
 
 
 /** @brief Prototype for decoding a complete RDF document file into a graph.

+ 1 - 1
include/lsup/codec/parser_nt.h

@@ -17,7 +17,7 @@
  *  N-Triples syntax for a IRI ref, Literal or BNode.
  */
 LSUP_rc
-LSUP_nt_parse_term (const char *rep, const LSUP_NSMap *map, LSUP_Term **term);
+LSUP_nt_parse_term (const char *rep, LSUP_Term **term);
 
 
 /** @brief Parse a N-Triples document from a file handle.

+ 8 - 2
include/lsup/environment.h

@@ -23,8 +23,14 @@
  * External variables.
  */
 
-/// Default namespace prefix map.
-extern LSUP_NSMap *LSUP_default_nsm;
+
+/** @brief Default context.
+ *
+ * The actual default context IRI used throughout the application may use a
+ * value from the `LSUP_DEFAULT_CTX_URI` environment variable.
+ */
+#define DEFAULT_CTX_LABEL LSUP_NS "default"
+
 /// Default context.
 extern LSUP_Term *LSUP_default_ctx;
 /// Serialized default context.

+ 28 - 30
include/lsup/graph.h

@@ -24,25 +24,43 @@ typedef struct graph_t LSUP_Graph;
 typedef struct graph_iter_t LSUP_GraphIterator;
 
 
-/** @brief Create an empty graph.
+/** @brief Create new graph.
  *
  * @param[in] store Back end store handle. It may be the result of
  * #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_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.
- *  If this is NULL, the graph is assigned a global namespace map
- *  (#LSUP_default_nsm) that lives until #LSUP_done() is called.
+ * @param[in] uri_str URI string of the new graph. It MUST be a non-prefixed
+ *  URI. For a namespace-prefixed URI, use #LSUP_graph_new_ns(). If NULL, a
+ *  UUID4 URN is generated.
  *
  * @return New graph, or NULL on error. Must be freed with #LSUP_graph_free().
  */
 LSUP_Graph *
-LSUP_graph_new (LSUP_Store *store, const char *uri_str, LSUP_NSMap *nsm);
+LSUP_graph_new (LSUP_Store *store, const char *uri_str);
+
+
+/** @brief Create an empty graph using a namespace-prefixed string for its URI.
+ *
+ * @param[in] store Back end store handle. It may be the result of
+ * #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_str URI string of the new graph. It MUST be a namespace-
+ *  prefixed URI registered in the global namespace map. It cannot be NULL.
+ *
+ * @return New graph, or NULL on error. Must be freed with #LSUP_graph_free().
+ */
+inline LSUP_Graph *
+LSUP_graph_new_ns (LSUP_Store *store, const char *ns_str) {
+    char *uri_str;
+    RCNL (LSUP_nsmap_normalize_uri (ns_str, &uri_str));
+
+    LSUP_Graph *gr = LSUP_graph_new (store, uri_str);
+    free (uri_str);
+
+    return gr;
+};
 
 
 /** @brief Create a temp graph from stored triples.
@@ -225,26 +243,6 @@ LSUP_rc
 LSUP_graph_set_uri (LSUP_Graph *gr, const char *uri_str);
 
 
-/** @brief Get the namespace map for an in-memory graph.
- *
- * @return Namespace handler for in-memory graphs, NULL for MDB graphs.
- */
-LSUP_NSMap *
-LSUP_graph_namespace (const LSUP_Graph *gr);
-
-
-/** @brief Set the namespace map for an in-memory graph.
- *
- * This has no effect on graph stores with LSUP_STORE_PERM.
- *
- * @param[in] gr Graph to set the namespace map for.
- *
- * @param[in] nsm Namespace handle.
- */
-void
-LSUP_graph_set_namespace (LSUP_Graph *gr, LSUP_NSMap *nsm);
-
-
 /** @brief Number of triples in a graph.
  *
  * @param gr Graph handle.

+ 18 - 35
include/lsup/namespace.h

@@ -3,7 +3,7 @@
 
 #include "hashmap.h"
 
-#include "core.h"
+#include "lsup/core.h"
 
 
 /** @defgroup namespace Namespace module
@@ -16,36 +16,25 @@
 #define PFX_LEN 8
 
 
-/** @brief Namespace map structure.
- *
- * 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.
- *
- * Prefixes are fixed PFX_LEN-size strings, namespaces are arbitrary sized
- * strings.
- */
-typedef struct hashmap LSUP_NSMap;
-
 /** @brief Namespace prefix type.
  */
 typedef char LSUP_ns_pfx[PFX_LEN];
 
 
-/** @brief Create a new namespace map.
- *
- * @return A pointer to an empty map. It must be freed with #LSUP_nsmap_free().
+/** @brief Prefix / Namespace pair.
  */
-LSUP_NSMap *
-LSUP_nsmap_new (void);
+typedef struct ns_entry_t {
+    LSUP_ns_pfx         pfx;        // Namespace prefix.
+    char *              ns;         // Fully qualified NS.
+} NSEntry;
 
 
-/** @brief Free a namespace map and its internal structures.
+/** @brief Default namespace prefix map.
  *
- * @param[in] map The map to free.
+ * This is a singleton. It gets created with #LSUP_init() and freed with
+ * #LSUP_done().
  */
-void
-LSUP_nsmap_free (LSUP_NSMap *map);
+extern struct hashmap *LSUP_default_nsm;
 
 
 /** @brief Add a prefix -> namespace pair to the map or update it.
@@ -62,7 +51,7 @@ LSUP_nsmap_free (LSUP_NSMap *map);
  * allocation error occurred.
  */
 LSUP_rc
-LSUP_nsmap_add (LSUP_NSMap *map, const char *pfx, const char *nsstr);
+LSUP_nsmap_add (const char *pfx, const char *nsstr);
 
 
 /** @brief Remove a prefix -> namespace pair from a map.
@@ -74,7 +63,7 @@ LSUP_nsmap_add (LSUP_NSMap *map, const char *pfx, const char *nsstr);
  * @return LSUP_OK on successful delete; LSUP_NOACTION if no record was found.
  */
 LSUP_rc
-LSUP_nsmap_remove (LSUP_NSMap *map, const char *pfx);
+LSUP_nsmap_remove (const char *pfx);
 
 
 /** @brief Get the namespace for a prefix.
@@ -87,7 +76,7 @@ LSUP_nsmap_remove (LSUP_NSMap *map, const char *pfx);
  *  should not be modified directly.
  */
 const char *
-LSUP_nsmap_get_ns (const LSUP_NSMap *map, const char *pfx);
+LSUP_nsmap_get_ns (const char *pfx);
 
 
 /** @brief Get the prefix for a namespace.
@@ -99,12 +88,10 @@ LSUP_nsmap_get_ns (const LSUP_NSMap *map, const char *pfx);
  * @return Found prefix, or NULL if the namespace is not mapped.
  */
 const char *
-LSUP_nsmap_get_pfx (const LSUP_NSMap *map, const char *ns);
+LSUP_nsmap_get_pfx (const char *ns);
 
 
 /** @brief Convert a namespace-prefixed string to a FQ URI sring if mapped.
- *
- * @param[in] map Namespace map to look up.
  *
  * @param[in] pfx_uri URI string to denormalize.
  *
@@ -118,8 +105,7 @@ LSUP_nsmap_get_pfx (const LSUP_NSMap *map, const char *ns);
  *  LSUP_MEM_ERR if a memory allocation error ocurred.
  */
 LSUP_rc
-LSUP_nsmap_normalize_uri (
-        const LSUP_NSMap *map, const char *pfx_uri, char **fq_uri);
+LSUP_nsmap_normalize_uri (const char *pfx_uri, char **fq_uri);
 
 
 /** @brief Convert a FQ URI string to a prefixed string if the prefix is found.
@@ -130,8 +116,6 @@ LSUP_nsmap_normalize_uri (
  * `http://example.edu/data/51937642` is being denormalized). In such
  * case, the first prefix that is found is assigned.
  *
- * @param[in] map Namespace map to look up.
- *
  * @param[in] fq_uri URI string to normalize.
  *
  * @param[out] pfx_uri String pointer to be filled with the prefixed URI. The
@@ -144,11 +128,10 @@ LSUP_nsmap_normalize_uri (
  *  LSUP_MEM_ERR if a memory allocation error ocurred.
  */
 LSUP_rc
-LSUP_nsmap_denormalize_uri (
-        const LSUP_NSMap *map, const char *fq_uri, char **pfx_uri);
+LSUP_nsmap_denormalize_uri (const char *fq_uri, char **pfx_uri);
 
 
-/** @brief Dump all entries of a namespace map.
+/** @brief Dump all entries of the namespace map.
  *
  * @param[in] map Map to dump.
  *
@@ -165,7 +148,7 @@ LSUP_nsmap_denormalize_uri (
  *      free (nsm_data);
  */
 const char ***
-LSUP_nsmap_dump (const LSUP_NSMap *map);
+LSUP_nsmap_dump (void);
 
 /// @}  END defgroup namespace
 #endif

+ 28 - 36
include/lsup/term.h

@@ -34,7 +34,6 @@ typedef enum {
                             ///<
                             ///< Invalid for most operations.
     LSUP_TERM_IRIREF,       ///< IRI reference.
-    LSUP_TERM_NS_IRIREF,    ///< Namespace-prefixed IRI reference.
     LSUP_TERM_LITERAL,      ///< Literal without language tag.
     LSUP_TERM_LT_LITERAL,   ///< Language-tagged string literal.
     LSUP_TERM_BNODE,        ///< Blank node.
@@ -59,11 +58,6 @@ typedef struct term_t {
 } LSUP_Term;
 
 
-/** @brief Shorthand to test if a term is a IRI of any kind.
- */
-#define LSUP_IS_IRI(term) \
-    ((term)->type == LSUP_TERM_IRIREF || (term)->type == LSUP_TERM_NS_IRIREF)
-
 /** @brief Shorthand to test if a term is a literal of any kind.
  */
 #define LSUP_IS_LITERAL(term) \
@@ -160,9 +154,8 @@ extern LSUP_TermSet *LSUP_term_cache;
  *  or langtag, etc. It may be NULL for IRI refs and BNodes, in which case a
  *  random identifier is generated.
  *
- * @param[in] metadata Namespace map (LSUP_NSMap *) for IRI refs; language tag
- * (LSUP_LangTag *) for language-tagged literals; or data type (LSUP_Term *)
- * for other literals. It may be NULL.
+ * @param[in] metadata language tag (LSUP_LangTag *) for language-tagged
+ * literals; or data type (LSUP_Term *) for other literals. It may be NULL.
  *
  * @return New term, which must be freed with #LSUP_term_free after use; or
  *  NULL on error.
@@ -176,34 +169,44 @@ LSUP_term_new (LSUP_TermType type, const char *data, void *metadata);
 #define TERM_DUMMY LSUP_term_new (LSUP_TERM_UNDEFINED, NULL, NULL)
 
 
-/** @brief Shortcut to create an IRI reference.
+/** @brief Create an IRI reference.
  *
  * Must be freed with #LSUP_term_free.
  *
- * @param[in] data The URI string. If NULL, a UUID4-based URN is generated.
- *  This cannot be NULL if the nsm parameter is not NULL.
+ * @param[in] data The fully qualified URI. If NULL, a UUID4 URN is generated.
+ *
+ * @return same as #LSUP_term_new().
+ */
+inline LSUP_Term *
+LSUP_iriref_new (const char *data)
+{ return LSUP_term_new (LSUP_TERM_IRIREF, data, NULL); }
+
+
+/** @brief Create an IRI reference from a namespace-prefixed string.
+ *
+ * Must be freed with #LSUP_term_free.
  *
- * @param[in] nsm Namespace map. If not NULL, a namespace-prefixed
- *  (#LSUP_TERM_NS_IRIREF) is created, otherwise a regular one
- *  (#LSUP_TERM_IRIREF).
+ * @param[in] data Namespace-prefixed URI. It MUST NOT be NULL,
  *
  * @return same as #LSUP_term_new().
  */
 inline LSUP_Term *
-LSUP_iriref_new (const char *data, LSUP_NSMap *nsm)
+LSUP_iriref_new_ns (const char *data)
 {
-    return (
-            nsm ? LSUP_term_new (LSUP_TERM_NS_IRIREF, data, nsm) :
-            LSUP_term_new (LSUP_TERM_IRIREF, data, NULL));
+    char *fquri;
+    RCNL (LSUP_nsmap_normalize_uri (data, &fquri));
+
+    LSUP_Term *t = LSUP_term_new (LSUP_TERM_IRIREF, fquri, NULL);
+    free (fquri);
+
+    return t;
 }
 
 
 /** @brief Create a new absolute IRI from a path relative to a root IRI.
  *
- * The term is always of type LSUP_TERM_IRIREF (i.e. not namespace-prefixed).
- *
- * If the provided IRI is already a fully qualified IRI (i.e. it has a prefix)
- * the result is semantically identical to the input.
+ * If the provided IRI is already an absolute IRI, the result is semantically
+ * identical to the input.
  *
  * If the relative IRI begins with a '/', the resulting IRI is relative to the
  * web root of the root IRI. I.e. if a root IRI has a path after the webroot,
@@ -218,7 +221,7 @@ LSUP_iriref_new (const char *data, LSUP_NSMap *nsm)
  * @return New absolute IRI, or NULL if either term is not an IRI.
  */
 LSUP_Term *
-LSUP_iriref_absolute (const LSUP_Term *root, const LSUP_Term *iri);
+LSUP_iriref_new_abs (const LSUP_Term *root, const LSUP_Term *iri);
 
 
 /** @brief Create a new relative IRI from an absolute IRI and a web root IRI.
@@ -234,7 +237,7 @@ LSUP_iriref_absolute (const LSUP_Term *root, const LSUP_Term *iri);
  * not a path under the root IRI, the result will be identical to the input.
  */
 LSUP_Term *
-LSUP_iriref_relative (const LSUP_Term *root, const LSUP_Term *iri);
+LSUP_iriref_new_rel (const LSUP_Term *root, const LSUP_Term *iri);
 
 
 /** @brief Shortcut to create a literal term.
@@ -332,17 +335,6 @@ void
 LSUP_term_free (LSUP_Term *term);
 
 
-/** @brief Namespace map of a IRI ref.
- *
- * @param[in] iri IRI reference handle.
- *
- * @return A pointer to the namespace map associated with the IRI. It is
- *  freed at program shutdown.
- */
-LSUP_NSMap *
-LSUP_iriref_nsm (const LSUP_Term *iri);
-
-
 /** @brief Get the prefix portion of a IRI ref.
  *
  * @param[in] iri IRI reference handle.

+ 4 - 8
src/codec/codec_nt.c

@@ -5,7 +5,6 @@
 typedef struct {
     const LSUP_Codec *  codec;      // Codec that generated this iterator.
     LSUP_GraphIterator *gr_it;      // Graph iterator.
-    const LSUP_NSMap *  nsm;        // Namespace map.
     size_t              cur;        // Internal cursor.
     LSUP_rc             rc;         // Internal return code.
     char *              str_s,      // Temporary string.
@@ -18,7 +17,7 @@ typedef struct {
 /* * * Codec functions. * * */
 
 static LSUP_rc
-term_to_nt (const LSUP_Term *term, const LSUP_NSMap *nsm, char **out_p)
+term_to_nt (const LSUP_Term *term, char **out_p)
 {
     LSUP_rc rc;
     char *out = NULL, *escaped;
@@ -27,8 +26,6 @@ term_to_nt (const LSUP_Term *term, const LSUP_NSMap *nsm, char **out_p)
 
     char *data = term->data;
     switch (term->type) {
-        case LSUP_TERM_NS_IRIREF:
-            LSUP_nsmap_normalize_uri (nsm, term->data, &data);
         case LSUP_TERM_IRIREF:
             out = realloc (*out_p, strlen (data) + 3);
             if (UNLIKELY (!out)) return LSUP_MEM_ERR;
@@ -118,7 +115,6 @@ gr_to_nt_init (const LSUP_Graph *gr)
 
     it->codec = &nt_codec;
     it->gr_it = LSUP_graph_lookup(gr, NULL, NULL, NULL, &it->cur);
-    it->nsm = LSUP_graph_namespace (gr);
 
     return it;
 }
@@ -131,9 +127,9 @@ gr_to_nt_iter (void *h, char **res) {
     LSUP_rc rc = LSUP_graph_iter_next (it->gr_it, &spo);
     if (rc != LSUP_OK) goto finally;
 
-    term_to_nt (spo->s, it->nsm, &it->str_s);
-    term_to_nt (spo->p, it->nsm, &it->str_p);
-    term_to_nt (spo->o, it->nsm, &it->str_o);
+    term_to_nt (spo->s, &it->str_s);
+    term_to_nt (spo->p, &it->str_p);
+    term_to_nt (spo->o, &it->str_o);
     LSUP_triple_free (spo);
 
     // 3 term separators + dot + newline + terminal = 6

+ 10 - 30
src/codec/codec_ttl.c

@@ -23,7 +23,7 @@ typedef struct {
 /* * * Codec functions. * * */
 
 static LSUP_rc
-term_to_ttl (const LSUP_Term *term, const LSUP_NSMap *nsm, char **out_p)
+term_to_ttl (const LSUP_Term *term, char **out_p)
 {
     LSUP_rc rc;
     char *tmp = NULL, *out = NULL;
@@ -38,7 +38,7 @@ term_to_ttl (const LSUP_Term *term, const LSUP_NSMap *nsm, char **out_p)
                 buf_len = 2;
                 tmp = "a";
             } else {
-                md_rc = LSUP_nsmap_denormalize_uri (nsm, term->data, &tmp);
+                md_rc = LSUP_nsmap_denormalize_uri (term->data, &tmp);
                 PRCCK (md_rc);
                 if (md_rc == LSUP_NORESULT) {
                     // If URI counld not be shortened, add `<>`
@@ -55,21 +55,6 @@ term_to_ttl (const LSUP_Term *term, const LSUP_NSMap *nsm, char **out_p)
             rc = LSUP_OK;
             break;
 
-        case LSUP_TERM_NS_IRIREF:
-            if (strcmp (term->data, LSUP_RDF_TYPE_NS) == 0) {
-                // Shorten RDF type
-                tmp = "a";
-                buf_len = 2;
-            } else {
-                tmp = term->data;
-                buf_len = strlen (term->data) + 1;
-            }
-            out = realloc (*out_p, buf_len);
-            if (UNLIKELY (!out)) return LSUP_MEM_ERR;
-            strcpy (out, tmp);
-            rc = LSUP_OK;
-            break;
-
         case LSUP_TERM_LITERAL:
             // Calculate string length.
             if (escape_lit (term->data, &tmp) != LSUP_OK)
@@ -83,7 +68,7 @@ term_to_ttl (const LSUP_Term *term, const LSUP_NSMap *nsm, char **out_p)
                 && term->datatype != LSUP_default_datatype
             ) {
                 md_rc = LSUP_nsmap_denormalize_uri (
-                        nsm, term->datatype->data, &metadata);
+                        term->datatype->data, &metadata);
                 PRCCK (md_rc);
                 unsigned padding = 0;
 
@@ -193,7 +178,7 @@ build_prolog (LSUP_TTLCodecIterator *it, char **res_p)
 {
     char *res = fmt_header ("# ");
 
-    const char ***nsm = LSUP_nsmap_dump (LSUP_graph_namespace (it->gr));
+    const char ***nsm = LSUP_nsmap_dump ();
     char *ns_tpl = "@prefix %s: <%s> .\n";
 
     // Prefix map.
@@ -211,16 +196,12 @@ build_prolog (LSUP_TTLCodecIterator *it, char **res_p)
     free (nsm);
 
     // Base.
-    char *base_uri_str = NULL;
-    LSUP_rc rc = LSUP_nsmap_denormalize_uri (
-            LSUP_graph_namespace (it->gr), LSUP_graph_uri (it->gr)->data,
-            &base_uri_str);
-    PRCCK (rc);
+    char *base_uri_str = LSUP_graph_uri (it->gr)->data;
     char *base_stmt_tpl = "\n@base <%s> .\n\n";
-    char *base_stmt = malloc (strlen (base_stmt_tpl) + strlen (base_uri_str));
+    char *base_stmt = malloc (
+            strlen (base_stmt_tpl) + strlen (base_uri_str) + 1);
     if (!UNLIKELY (base_stmt)) return LSUP_MEM_ERR;
     sprintf (base_stmt, base_stmt_tpl, base_uri_str);
-    free (base_uri_str);
     res = realloc (res, strlen (res) + strlen (base_stmt) + 1);
     if (!UNLIKELY (res)) return LSUP_MEM_ERR;
     res = strcat (res, base_stmt);
@@ -244,7 +225,7 @@ gr_to_ttl_iter (void *h, char **res_p) {
     char *res = *res_p;  // Result string will be reallocated.
     RCCK (LSUP_term_set_next (it->subjects, &it->s_cur, &s));
 
-    term_to_ttl (s, LSUP_graph_namespace (it->gr), &res);
+    term_to_ttl (s, &res);
 
     LSUP_LinkMap *lmap = LSUP_graph_connections (
             it->gr, s, LSUP_LINK_OUTBOUND);
@@ -256,7 +237,7 @@ gr_to_ttl_iter (void *h, char **res_p) {
     // Begin predicate loop.
     while (LSUP_link_map_next (lmit, &p, &o_ts) != LSUP_END) {
         // Add predicate representation.
-        RCCK (term_to_ttl (p, LSUP_graph_namespace (it->gr), &it->p_str));
+        RCCK (term_to_ttl (p, &it->p_str));
         char *tmp = realloc (
                 res, strlen (res) + strlen (it->p_str) + strlen (p_join) + 1);
         if (UNLIKELY (!tmp)) goto memfail;
@@ -269,8 +250,7 @@ gr_to_ttl_iter (void *h, char **res_p) {
         LSUP_Term *o = NULL;
         char *o_join = " ";
         while (LSUP_term_set_next (o_ts, &i, &o) != LSUP_END) {
-            it->rc = term_to_ttl (
-                    o, LSUP_graph_namespace (it->gr), &it->o_str);
+            it->rc = term_to_ttl (o, &it->o_str);
             RCCK (it->rc);
             char *tmp = realloc (
                     res, strlen (res) + strlen (it->o_str) + strlen (o_join) + 1);

+ 17 - 56
src/codec/grammar_ttl.y

@@ -61,11 +61,7 @@ statement   ::= triples .
 statement   ::= WS .
 
 prefixID    ::= PREFIX(P) WS IRIREF(N) PERIOD . {
-                LSUP_nsmap_add (
-                    LSUP_graph_namespace (
-                        LSUP_graph_iter_graph (state->it)
-                    ), P, N
-                );
+                LSUP_nsmap_add (P, N);
 
                 free (P);
                 free (N);
@@ -73,7 +69,7 @@ prefixID    ::= PREFIX(P) WS IRIREF(N) PERIOD . {
 
 base        ::= BASE WS IRIREF(D) PERIOD . {
                 LSUP_term_free (state->base);
-                state->base = LSUP_iriref_new (D, NULL);
+                state->base = LSUP_iriref_new (D);
 
                 free (D);
             }
@@ -128,11 +124,7 @@ subject 	::= blank(D) . { state->lms = D; }
 %type predicate { LSUP_Term * }
 %destructor predicate { LSUP_term_free ($$); }
 predicate   ::= resource .
-predicate(A)::= RDF_TYPE . {
-                A = LSUP_iriref_new (
-                        "rdf:type",
-                        LSUP_graph_namespace (LSUP_graph_iter_graph (state->it)));
-                }
+predicate(A)::= RDF_TYPE . { A = LSUP_iriref_new_ns ("rdf:type"); }
 
 %type object { LSUP_Term * }
 %destructor object { LSUP_term_free ($$); }
@@ -143,79 +135,53 @@ object 	    ::= literal .
 %type literal { LSUP_Term * }
 %destructor literal { LSUP_term_free ($$); }
 literal(A)  ::= STRING(D) . {
-                A = LSUP_term_new (LSUP_TERM_LITERAL, D, NULL);
+                A = LSUP_literal_new (D, NULL);
                 LOG_TRACE("Created plain literal: \"%s\"", A->data);
                 free (D);
             }
 literal(A)  ::= STRING(D) LANGTAG(L) . {
-                A = LSUP_term_new (LSUP_TERM_LT_LITERAL, D, L);
+                A = LSUP_lt_literal_new (D, L);
                 LOG_TRACE("Created LT-literal: \"%s\"@%s", A->data, A->lang);
                 free (D);
                 free (L);
             }
 literal(A)  ::= STRING(D) DTYPE_MARKER resource(M) . {
-                A = LSUP_term_new (LSUP_TERM_LITERAL, D, M);
+                A = LSUP_literal_new (D, M);
                 LOG_TRACE(
                         "Created DT-literal: \"%s\"^^%s",
                         A->data, A->datatype);
                 free (D);
             }
 literal(A)  ::= INTEGER(D) . {
-                A = LSUP_term_new (
-                    LSUP_TERM_LITERAL, D,
-                    LSUP_iriref_new (
-                        "xsd:integer", 
-                        LSUP_graph_namespace (LSUP_graph_iter_graph (state->it))
-                    )
-                );
-
+                A = LSUP_literal_new (D, LSUP_iriref_new_ns ("xsd:integer"));
                 free (D);
             }
 literal(A)  ::= DOUBLE(D) . {
-                A = LSUP_term_new (
-                    LSUP_TERM_LITERAL, D,
-                    LSUP_iriref_new (
-                        "xsd:double", 
-                        LSUP_graph_namespace (LSUP_graph_iter_graph (state->it))
-                    )
-                );
+                A = LSUP_literal_new (D, LSUP_iriref_new_ns ("xsd:double"));
                 free (D);
             }
 literal(A)  ::= DECIMAL(D) . {
-                A = LSUP_term_new (
-                    LSUP_TERM_LITERAL, D,
-                    LSUP_iriref_new (
-                        "xsd:decimal", 
-                        LSUP_graph_namespace (LSUP_graph_iter_graph (state->it))
-                    )
-                );
+                A = LSUP_literal_new (D, LSUP_iriref_new_ns ("xsd:decimal"));
                 free (D);
             }
 literal(A)  ::= BOOLEAN(D) . {
-                A = LSUP_term_new (
-                    LSUP_TERM_LITERAL, D,
-                    LSUP_iriref_new (
-                        "xsd:boolean", 
-                        LSUP_graph_namespace (LSUP_graph_iter_graph (state->it))
-                    )
-                );
+                A = LSUP_literal_new (D, LSUP_iriref_new_ns ("xsd:boolean"));
                 free (D);
             }
 
 %type blank { LSUP_Term * }
 %destructor blank { LSUP_term_free ($$); }
 blank(A)    ::= BNODE_ID(D) . {
-                A = LSUP_term_new (LSUP_TERM_BNODE, D, NULL);
+                A = LSUP_bnode_new (D);
                 LOG_TRACE("Created blank node: _:%s", A->data);
-
                 free (D);
             }
 blank(A)    ::= LBRACKET RBRACKET . [BNODE_ID] {
-                A = LSUP_term_new (LSUP_TERM_BNODE, NULL, NULL);
+                A = LSUP_bnode_new (NULL);
                 LOG_TRACE("Created empty list BN: _:%s", A->data);
             }
 blank(A)    ::= LBRACKET predObjList(L) RBRACKET . [BNODE_ID] {
-                A = LSUP_term_new (LSUP_TERM_BNODE, NULL, NULL);
+                A = LSUP_bnode_new (NULL);
                 state->lms = A;
                 state->ct += LSUP_graph_add_link_map (state->it, L);
                 LOG_TRACE("Created list BN: _:%s", A->data);
@@ -224,10 +190,7 @@ blank(A)    ::= LBRACKET predObjList(L) RBRACKET . [BNODE_ID] {
             }
 blank       ::= collection . [BNODE_ID]
 blank(A)    ::= LPAREN RPAREN . [BNODE_ID] {
-                A = LSUP_iriref_new (
-                    "rdf:nil",
-                    LSUP_graph_namespace (LSUP_graph_iter_graph (state->it))
-                );
+                A = LSUP_iriref_new_ns ("rdf:nil");
                 LOG_TRACE("Created list terminator: %s", A->data);
             }
 
@@ -255,10 +218,10 @@ itemList(A) ::= object(O) . {
 %type resource { LSUP_Term * }
 %destructor resource { LSUP_term_free ($$); }
 resource(A) ::= IRIREF(D) . {
-                LSUP_Term *rel_iri = LSUP_iriref_new (D, NULL);
+                LSUP_Term *rel_iri = LSUP_iriref_new (D);
                 free (D);
                 if (state->base) {
-                    A = LSUP_iriref_absolute (rel_iri, state->base);
+                    A = LSUP_iriref_new_abs (rel_iri, state->base);
                     LSUP_term_free (rel_iri);
                 } else {
                     A = rel_iri;
@@ -266,9 +229,7 @@ resource(A) ::= IRIREF(D) . {
                 LOG_TRACE("Created IRI: <%s>", A->data);
             }
 resource(A) ::= QNAME(D) . {
-                A = LSUP_iriref_new (
-                    D, LSUP_graph_namespace (LSUP_graph_iter_graph (state->it))
-                );
+                A = LSUP_iriref_new_ns (D);
                 LOG_TRACE("Created IRI: %s", A->data);
                 free (D);
             }

+ 4 - 5
src/codec/lexer_nt.re

@@ -131,7 +131,7 @@ loop:
 
         LOG_DEBUG("URI data: %s", data);
 
-        *term = LSUP_iriref_new ((char*)data, NULL);
+        *term = LSUP_iriref_new ((char*)data);
         free (data);
 
         if (!UNLIKELY (term)) return -1;
@@ -166,8 +166,7 @@ loop:
 
         if (type == LSUP_TERM_LITERAL) {
             LSUP_Term *dtype;
-            dtype = (
-                metadata ? LSUP_iriref_new ((char *) metadata, NULL) : NULL);
+            dtype = (metadata ? LSUP_iriref_new ((char *) metadata) : NULL);
 
             *term = LSUP_literal_new ((char *) data, dtype);
 
@@ -229,7 +228,7 @@ loop:
 
 
 LSUP_rc
-LSUP_nt_parse_term (const char *rep, const LSUP_NSMap *map, LSUP_Term **term)
+LSUP_nt_parse_term (const char *rep, LSUP_Term **term)
 {
     FILE *fh = fmemopen ((void *)rep, strlen (rep), "r");
 
@@ -267,7 +266,7 @@ LSUP_nt_parse_doc (FILE *fh, LSUP_Graph **gr_p, size_t *ct, char **err_p)
 
     LSUP_rc rc;
 
-    LSUP_Graph *gr = LSUP_graph_new (NULL, NULL, NULL);
+    LSUP_Graph *gr = LSUP_graph_new (NULL, NULL);
     if (UNLIKELY (!gr)) return LSUP_MEM_ERR;
 
     LSUP_GraphIterator *it = LSUP_graph_add_init (gr);

+ 1 - 1
src/codec/lexer_ttl.re

@@ -376,7 +376,7 @@ LSUP_ttl_parse_doc (FILE *fh, LSUP_Graph **gr_p, size_t *ct, char **err_p)
     void *parser = TTLParseAlloc (malloc);
 
     // TODO add basic NS, critically xsd: and rdf:
-    LSUP_Graph *gr = LSUP_graph_new (NULL, NULL, NULL);
+    LSUP_Graph *gr = LSUP_graph_new (NULL, NULL);
     if (UNLIKELY (!gr)) return LSUP_MEM_ERR;
 
     state->it = LSUP_graph_add_init (gr);

+ 33 - 14
src/environment.c

@@ -2,22 +2,35 @@
 #include "lsup/data/bootstrap.h"
 
 
-/** @brief Default context.
- *
- * The actual default context IRI used throughout the application may use a
- * value from the `LSUP_DEFAULT_CTX_URI` environment variable.
- */
-#define DEFAULT_CTX_LABEL LSUP_NS "default"
-
-
 /*
  * External variables.
  */
-LSUP_NSMap *LSUP_default_nsm = NULL;
 LSUP_Term *LSUP_default_ctx = NULL;
 LSUP_Buffer *LSUP_default_ctx_buf = NULL;
 
 
+/**
+ * Callbacks.
+ */
+static int nsmap_comp_fn (const void *a, const void *b, void *udata)
+{
+    const NSEntry *nsa = a;
+    const NSEntry *nsb = b;
+
+    return strncmp (nsa->pfx, nsb->pfx, PFX_LEN);
+}
+
+static uint64_t nsmap_hash_fn (
+        const void *item, uint64_t seed0, uint64_t seed1)
+{
+    const NSEntry *nse = item;
+    return (uint64_t) LSUP_HASH64 (nse->pfx, strlen (nse->pfx), seed0);
+}
+
+static void nsmap_free_fn (void *item)
+{ free (((NSEntry *) item)->ns); }
+
+
 /*
  * API
  */
@@ -40,15 +53,21 @@ LSUP_init (void)
     log_set_level (loglevel);
 
     // Default namespace map.
-    LSUP_default_nsm = LSUP_nsmap_new();
+    LSUP_default_nsm = hashmap_new (
+            sizeof (NSEntry), 0, LSUP_HASH_SEED, 0,
+            nsmap_hash_fn, nsmap_comp_fn, nsmap_free_fn, NULL);
+
+    if (hashmap_oom (LSUP_default_nsm)) return LSUP_MEM_ERR;
+
+
     if (UNLIKELY (!LSUP_default_nsm)) return LSUP_ERROR;
     for (int i = 0; init_nsmap[i][0] != NULL; i++)
-        LSUP_nsmap_add (LSUP_default_nsm, init_nsmap[i][0], init_nsmap[i][1]);
+        LSUP_nsmap_add (init_nsmap[i][0], init_nsmap[i][1]);
 
     // Default context URI.
     const char *default_ctx_str = getenv ("LSUP_DEFAULT_CTX");
     if (!default_ctx_str) default_ctx_str = DEFAULT_CTX_LABEL;
-    LSUP_default_ctx = LSUP_iriref_new (default_ctx_str, NULL);
+    LSUP_default_ctx = LSUP_iriref_new (default_ctx_str);
     if (UNLIKELY (!LSUP_default_ctx)) return LSUP_ERROR;
     LSUP_default_ctx_buf = LSUP_term_serialize (LSUP_default_ctx);
     if (UNLIKELY (!LSUP_default_ctx_buf)) return LSUP_ERROR;
@@ -62,7 +81,7 @@ LSUP_init (void)
     // duplicates.
     // This is the last operation that can fail in this function, and it is
     // the indicator for LSUP_IS_INIT.
-    LSUP_default_datatype = LSUP_iriref_new (DEFAULT_DTYPE, NULL);
+    LSUP_default_datatype = LSUP_iriref_new (DEFAULT_DTYPE);
     LSUP_rc rc = LSUP_term_set_add (
             LSUP_term_cache, LSUP_default_datatype, NULL);
     PRCCK (rc);
@@ -84,7 +103,7 @@ LSUP_done (void)
     // Free default NS map and context.
     LSUP_buffer_free (LSUP_default_ctx_buf);
     LSUP_term_free (LSUP_default_ctx);
-    LSUP_nsmap_free (LSUP_default_nsm);
+    hashmap_free (LSUP_default_nsm);
 
     // Free ID cache, including default literal datatype.
     hashmap_free (LSUP_term_cache);

+ 18 - 35
src/graph.c

@@ -7,11 +7,6 @@
 struct graph_t {
     LSUP_Term               *uri;           ///< Graph "name" (URI).
     LSUP_Store *            store;          ///< Store handle.
-    LSUP_NSMap *            nsm;            /**< Namespace map.
-                                              *
-                                              * NOTE: This is
-                                              * NULL for permanent stores.
-                                              */
 };
 
 struct graph_iter_t {
@@ -42,7 +37,7 @@ check_backend (LSUP_StoreType be)
  */
 
 LSUP_Graph *
-LSUP_graph_new (LSUP_Store *store, const char *uri_str, LSUP_NSMap *nsm)
+LSUP_graph_new (LSUP_Store *store, const char *uri_str)
 {
     // Create a HTable graph by default.
     LSUP_Graph *gr;
@@ -51,11 +46,9 @@ LSUP_graph_new (LSUP_Store *store, const char *uri_str, LSUP_NSMap *nsm)
     gr->store = (store) ? store : LSUP_store_new (
             LSUP_STORE_HTABLE, NULL, 0, false);
 
-    gr->nsm = nsm ? nsm : LSUP_default_nsm;
-
     gr->uri =
-        uri_str? LSUP_iriref_new (uri_str, gr->nsm) :
-        LSUP_iriref_new (NULL, NULL);
+        uri_str? LSUP_iriref_new (uri_str) :
+        LSUP_iriref_new (NULL);
 
     LOG_DEBUG ("Graph created.");
     return gr;
@@ -70,7 +63,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->data, NULL);
+    LSUP_Graph *gr = LSUP_graph_new (NULL, uri->data);
     LSUP_BufferTriple *sspo = BTRP_DUMMY;
     void *add_it = LSUP_graph_add_init_txn (txn, gr);
 
@@ -279,7 +272,7 @@ LSUP_graph_set_uri (LSUP_Graph *gr, const char *uri_str)
     LSUP_rc rc = LSUP_OK;
     LSUP_Buffer *old_sc = NULL, *new_sc = NULL;
 
-    LSUP_Term *uri = LSUP_iriref_new (uri_str, gr->nsm);
+    LSUP_Term *uri = LSUP_iriref_new (uri_str);
     if (UNLIKELY (!uri)) {
         rc = LSUP_MEM_ERR;
         goto finally;
@@ -312,16 +305,6 @@ finally:
 }
 
 
-LSUP_NSMap *
-LSUP_graph_namespace (const LSUP_Graph *gr)
-{ return gr->nsm; }
-
-
-void
-LSUP_graph_set_namespace (LSUP_Graph *gr, LSUP_NSMap *nsm)
-{ gr->nsm = nsm; }
-
-
 size_t
 LSUP_graph_size (const LSUP_Graph *gr)
 {
@@ -344,7 +327,7 @@ LSUP_graph_size (const LSUP_Graph *gr)
 bool
 LSUP_graph_equals (const LSUP_Graph *gr1, const LSUP_Graph *gr2)
 {
-    LSUP_Graph *res = LSUP_graph_new (NULL, NULL, NULL);
+    LSUP_Graph *res = LSUP_graph_new (NULL, NULL);
     LSUP_graph_bool_op (LSUP_BOOL_XOR, gr1, gr2, res);
     bool ret = (LSUP_graph_size (res) == 0);
 
@@ -381,11 +364,11 @@ LSUP_graph_add_iter (LSUP_GraphIterator *it, const LSUP_Triple *spo)
 
     // Make relative s and o.
     LSUP_Term *rel_s, *rel_o;
-    if (LSUP_IS_IRI (spo->s))
-        rel_s = LSUP_iriref_relative (it->graph->uri, spo->s);
+    if (spo->s->type == LSUP_TERM_IRIREF)
+        rel_s = LSUP_iriref_new_rel (it->graph->uri, spo->s);
     else rel_s = spo->s;
-    if (LSUP_IS_IRI (spo->o))
-        rel_o = LSUP_iriref_relative (it->graph->uri, spo->o);
+    if (spo->o->type == LSUP_TERM_IRIREF)
+        rel_o = LSUP_iriref_new_rel (it->graph->uri, spo->o);
     else rel_o = spo->o;
 
     LSUP_Triple *rel_spo = LSUP_triple_new (rel_s, spo->p, rel_o);
@@ -538,12 +521,12 @@ LSUP_graph_lookup_txn (
 
     // Make relative s and o.
     LSUP_Term *rel_s, *rel_o;
-    if (s && LSUP_IS_IRI (s)) {
-        rel_s = LSUP_iriref_relative (gr->uri, s);
+    if (s && s->type == LSUP_TERM_IRIREF) {
+        rel_s = LSUP_iriref_new_rel (gr->uri, s);
         LOG_DEBUG ("Relative S lookup: %s", rel_s->data);
     } else rel_s = (LSUP_Term *)s;
-    if (o && LSUP_IS_IRI (o)) {
-        rel_o = LSUP_iriref_relative (gr->uri, o);
+    if (o && o->type == LSUP_TERM_IRIREF) {
+        rel_o = LSUP_iriref_new_rel (gr->uri, o);
         LOG_DEBUG ("Relative O lookup: %s", rel_o->data);
     } else rel_o = (LSUP_Term *)o;
 
@@ -840,12 +823,11 @@ LSUP_graph_add_link_map (LSUP_GraphIterator *it, LSUP_LinkMap *lm)
 LSUP_Term *
 LSUP_bnode_add_collection (LSUP_GraphIterator *it, LSUP_TermSet *ts)
 {
-    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),
+        *rdf_first = LSUP_iriref_new ("rdf:first"),
+        *rdf_rest = LSUP_iriref_new ("rdf:rest"),
+        *rdf_nil = LSUP_iriref_new ("rdf:nil"),
         *link;
 
     LSUP_Triple *spo = TRP_DUMMY;
@@ -904,3 +886,4 @@ graph_iter_next_buffer (LSUP_GraphIterator *it)
  */
 
 size_t LSUP_graph_size (const LSUP_Graph *gr);
+LSUP_Graph * LSUP_graph_new_ns (LSUP_Store *store, const char *ns_str);

+ 32 - 73
src/namespace.c

@@ -1,14 +1,6 @@
-#include "lsup/core.h"
 #include "lsup/namespace.h"
 
 
-/** @brief Prefix / Namespace pair.
- */
-typedef struct ns_entry_t {
-    LSUP_ns_pfx         pfx;        // Namespace prefix.
-    char *              ns;         // Fully qualified NS.
-} NSEntry;
-
 /** @brief Iterator for dumping NS map.
  */
 struct dump_iter_t {
@@ -17,28 +9,6 @@ struct dump_iter_t {
 };
 
 
-/**
- * Callbacks.
- */
-static int nsmap_comp_fn (const void *a, const void *b, void *udata)
-{
-    const NSEntry *nsa = a;
-    const NSEntry *nsb = b;
-
-    return strncmp (nsa->pfx, nsb->pfx, PFX_LEN);
-}
-
-static uint64_t nsmap_hash_fn (
-        const void *item, uint64_t seed0, uint64_t seed1)
-{
-    const NSEntry *nse = item;
-    return (uint64_t) LSUP_HASH64 (nse->pfx, strlen (nse->pfx), seed0);
-}
-
-static void nsmap_free_fn (void *item)
-{ free (((NSEntry *) item)->ns); }
-
-
 // TODO expose in API as first-class iterator function.
 static bool nsmap_dump_ns_iter_fn (const void *item, void *udata)
 {
@@ -52,26 +22,24 @@ static bool nsmap_dump_ns_iter_fn (const void *item, void *udata)
     return true;
 }
 
+
 /**
  * API.
  */
 
-LSUP_NSMap *
-LSUP_nsmap_new (void)
-{
-    return hashmap_new (
-            sizeof (NSEntry), 0, LSUP_HASH_SEED, 0,
-            nsmap_hash_fn, nsmap_comp_fn, nsmap_free_fn, NULL);
-}
-
-
-void
-LSUP_nsmap_free (LSUP_NSMap *map)
-{ hashmap_free (map); }
+/*
+ * @note The internal functions to create and tear down this structure
+ * are in the environment module, while all functions for regular operations
+ * are in this module. This is because environment requires term, and term
+ * requires some namespace functions. This split is a bit awkward but it
+ * avoids circular dependencies; and anyways, nsm-related functions in the
+ * environment module are not exposed.
+ */
+struct hashmap *LSUP_default_nsm = NULL;
 
 
 LSUP_rc
-LSUP_nsmap_add (LSUP_NSMap *map, const char *pfx, const char *nsstr)
+LSUP_nsmap_add (const char *pfx, const char *nsstr)
 {
     NSEntry entry_s = {};
 
@@ -82,8 +50,8 @@ LSUP_nsmap_add (LSUP_NSMap *map, const char *pfx, const char *nsstr)
     strncpy (entry_s.pfx, pfx, PFX_LEN -1);
     entry_s.ns = strdup (nsstr);
 
-    const NSEntry *ret = hashmap_delete (map, &entry_s);
-    if (!ret) LOG_DEBUG("Adding prefix '%s' to NS map @%p.", entry_s.pfx, map);
+    const NSEntry *ret = hashmap_delete (LSUP_default_nsm, &entry_s);
+    if (!ret) LOG_DEBUG("Adding prefix '%s' to NS map.", entry_s.pfx);
     else {
         LOG_DEBUG(
                 "Replacing NS '%s' with '%s' for prefix '%s'.",
@@ -91,19 +59,19 @@ LSUP_nsmap_add (LSUP_NSMap *map, const char *pfx, const char *nsstr)
         // Free replaced NS string.
         free (ret->ns);
     }
-    hashmap_set (map, &entry_s);
-    if (hashmap_oom (map)) return LSUP_MEM_ERR;
+    hashmap_set (LSUP_default_nsm, &entry_s);
+    if (hashmap_oom (LSUP_default_nsm)) return LSUP_MEM_ERR;
 
     return LSUP_OK;
 }
 
 
 LSUP_rc
-LSUP_nsmap_remove (LSUP_NSMap *map, const char *pfx)
+LSUP_nsmap_remove (const char *pfx)
 {
     NSEntry entry_s = {};
     strncpy (entry_s.pfx, pfx, PFX_LEN - 1);
-    const NSEntry *entry = hashmap_delete (map, &entry_s);
+    const NSEntry *entry = hashmap_delete (LSUP_default_nsm, &entry_s);
 
     if (!entry) return LSUP_NOACTION;
 
@@ -114,22 +82,22 @@ LSUP_nsmap_remove (LSUP_NSMap *map, const char *pfx)
 
 
 const char *
-LSUP_nsmap_get_ns (const LSUP_NSMap *map, const char *pfx)
+LSUP_nsmap_get_ns (const char *pfx)
 {
     NSEntry entry_s = {};
     strncpy (entry_s.pfx, pfx, PFX_LEN - 1);
-    const NSEntry *entry = hashmap_get ((LSUP_NSMap *)map, &entry_s);
+    const NSEntry *entry = hashmap_get (LSUP_default_nsm, &entry_s);
 
     return (entry) ? entry->ns : NULL;
 }
 
 
 const char *
-LSUP_nsmap_get_pfx (const LSUP_NSMap *map, const char *ns)
+LSUP_nsmap_get_pfx (const char *ns)
 {
     const NSEntry *entry;
     size_t i = 0;
-    while (hashmap_iter ((LSUP_NSMap *)map, &i, (void **) &entry)) {
+    while (hashmap_iter (LSUP_default_nsm, &i, (void **) &entry)) {
         if (strncmp (entry->ns, ns, strlen (ns)) == 0)
             return entry->pfx;
     }
@@ -139,17 +107,15 @@ LSUP_nsmap_get_pfx (const LSUP_NSMap *map, const char *ns)
 
 
 LSUP_rc
-LSUP_nsmap_normalize_uri (
-        const LSUP_NSMap *map, const char *pfx_uri, char **fq_uri_p)
+LSUP_nsmap_normalize_uri (const char *pfx_uri, char **fq_uri_p)
 {
+    if (!pfx_uri) {
+        log_error ("Prefixed URI cannot be NULL.");
+        return LSUP_VALUE_ERR;
+    }
     LSUP_rc rc = LSUP_NORESULT;
     char *fq_uri = NULL;
 
-    if (UNLIKELY (!map)) {
-        log_warn ("No namespace map was passed for normalization.");
-        goto finally;
-    }
-
     size_t pfx_len = strcspn (pfx_uri, ":");
     if (pfx_len >= PFX_LEN || pfx_len == strlen (pfx_uri)) {
         log_warn (
@@ -162,7 +128,7 @@ LSUP_nsmap_normalize_uri (
     strncpy (pfx, pfx_uri, pfx_len);
     pfx[pfx_len] = '\0';
 
-    const char *ns = LSUP_nsmap_get_ns ((LSUP_NSMap *)map, pfx);
+    const char *ns = LSUP_nsmap_get_ns (pfx);
 
     if (ns) {
         // -1 for :, +1 for terminator.
@@ -184,8 +150,7 @@ finally:
 
 
 LSUP_rc
-LSUP_nsmap_denormalize_uri (
-        const LSUP_NSMap *map, const char *fq_uri, char **pfx_uri_p)
+LSUP_nsmap_denormalize_uri (const char *fq_uri, char **pfx_uri_p)
 {
     /*
      * This is different from LSUP_nsmap_get_ns, in that the URI being looked
@@ -198,13 +163,8 @@ LSUP_nsmap_denormalize_uri (
     const char *pfx = NULL;
     char *pfx_uri = NULL;
 
-    if (UNLIKELY (!map)) {
-        log_warn ("No namespace map was passed for denormalization.");
-        goto finally;
-    }
-
     size_t i = 0, offset;
-    while (hashmap_iter ((LSUP_NSMap *)map, &i, (void **) &entry)) {
+    while (hashmap_iter (LSUP_default_nsm, &i, (void **) &entry)) {
         offset = strlen (entry->ns);
         if (strncmp (entry->ns, fq_uri, offset) == 0) {
             pfx = entry->pfx;
@@ -221,7 +181,6 @@ LSUP_nsmap_denormalize_uri (
         rc = LSUP_OK;
     } else log_warn ("No NS prefix found in map to denormalize %s", fq_uri);
 
-finally:
     *pfx_uri_p = pfx_uri;
 
     return rc;
@@ -229,9 +188,9 @@ finally:
 
 
 const char ***
-LSUP_nsmap_dump (const LSUP_NSMap *map)
+LSUP_nsmap_dump (void)
 {
-    size_t i = hashmap_count ((LSUP_NSMap *) map);
+    size_t i = hashmap_count (LSUP_default_nsm);
 
     const char ***data = malloc (2 * (i + 1) * sizeof (char *));
     if (UNLIKELY (!data)) return NULL;
@@ -242,7 +201,7 @@ LSUP_nsmap_dump (const LSUP_NSMap *map)
     }
 
     struct dump_iter_t cur = {.i = 0, .data = data};
-    hashmap_scan ((LSUP_NSMap *) map, nsmap_dump_ns_iter_fn, &cur);
+    hashmap_scan (LSUP_default_nsm, nsmap_dump_ns_iter_fn, &cur);
     data[i] = NULL; // Sentinel
 
     return data;

+ 27 - 70
src/term.c

@@ -25,7 +25,6 @@ typedef struct match_coord_t {
 
 /// Matching sub-patterns for IRI parts.
 struct iri_info_t {
-    LSUP_NSMap *        nsm;        ///< NSM handle for prefixed IRI.
     MatchCoord          prefix;     ///< URI prefix (scheme + authority).
     MatchCoord          path;       ///< URI path (including fragment).
     MatchCoord          frag;       ///< URI fragment.
@@ -188,13 +187,10 @@ LSUP_term_copy (const LSUP_Term *src)
 {
     void *metadata = NULL;
 
-    if (LSUP_IS_IRI (src))
-        metadata = (void *) LSUP_iriref_nsm (src);
-    else if (src->type == LSUP_TERM_LITERAL)
+    if (src->type == LSUP_TERM_LITERAL)
         metadata = (void *) src->datatype;
-    else if (src->type == LSUP_TERM_LT_LITERAL) {
+    else if (src->type == LSUP_TERM_LT_LITERAL)
         metadata = (void *) src->lang;
-    }
 
     return LSUP_term_new (src->type, src->data, metadata);
 }
@@ -237,13 +233,13 @@ finally:
 
 
 LSUP_Term *
-LSUP_iriref_absolute (const LSUP_Term *root, const LSUP_Term *iri)
+LSUP_iriref_new_abs (const LSUP_Term *root, const LSUP_Term *iri)
 {
-    if (! LSUP_IS_IRI (iri)) {
+    if (iri->type != LSUP_TERM_IRIREF) {
         log_error ("Provided path is not an IRI.");
         return NULL;
     }
-    if (! LSUP_IS_IRI (root)) {
+    if (root->type != LSUP_TERM_IRIREF) {
         log_error ("Provided root is not an IRI.");
         return NULL;
     }
@@ -271,7 +267,7 @@ LSUP_iriref_absolute (const LSUP_Term *root, const LSUP_Term *iri)
     }
     free (pfx);
 
-    LSUP_Term *ret = LSUP_iriref_new (data, NULL);
+    LSUP_Term *ret = LSUP_iriref_new (data);
     if (data != iri->data) free (data);
 
     return ret;
@@ -279,13 +275,13 @@ LSUP_iriref_absolute (const LSUP_Term *root, const LSUP_Term *iri)
 
 
 LSUP_Term *
-LSUP_iriref_relative (const LSUP_Term *root, const LSUP_Term *iri)
+LSUP_iriref_new_rel (const LSUP_Term *root, const LSUP_Term *iri)
 {
-    if (! LSUP_IS_IRI (iri)) {
+    if (iri->type != LSUP_TERM_IRIREF) {
         log_error ("Provided path is not an IRI.");
         return NULL;
     }
-    if (! LSUP_IS_IRI (root)) {
+    if (root->type != LSUP_TERM_IRIREF) {
         log_error ("Provided root is not an IRI.");
         return NULL;
     }
@@ -294,7 +290,7 @@ LSUP_iriref_relative (const LSUP_Term *root, const LSUP_Term *iri)
             strstr (iri->data, root->data) == iri->data ?
             strlen (root->data) : 0);
 
-    return LSUP_iriref_new (iri->data + offset, LSUP_iriref_nsm (iri));
+    return LSUP_iriref_new (iri->data + offset);
 }
 
 
@@ -315,32 +311,18 @@ LSUP_term_serialize (const LSUP_Term *term)
     LSUP_Term *tmp_term;
     void *metadata = NULL;
 
-    if (term->type == LSUP_TERM_NS_IRIREF) {
-        // For IRI refs, simply serialize the FQ version of the term.
-        char *fq_uri;
-
-        if (LSUP_nsmap_normalize_uri (
-            term->iri_info->nsm, term->data, &fq_uri
-        ) < LSUP_OK) return NULL;
-
-        tmp_term = LSUP_iriref_new (fq_uri, NULL);
-        free (fq_uri);
-
-    } else if (term->type == LSUP_TERM_LT_LITERAL) {
+    if (term->type == LSUP_TERM_LT_LITERAL) {
         // For LT literals with empty lang tag, convert to a normal xsd:string.
         if (strlen (term->lang) == 0)
             tmp_term = LSUP_literal_new (term->data, NULL);
-        else tmp_term = LSUP_lt_literal_new (term->data, (char *) term->lang);
-
-    } else tmp_term = LSUP_term_new (
-            term->type, term->data, (void *) term->datatype);
-    // "datatype" can be anything here since it's cast to void *.
-
-    // metadata field is ignored for IRI ref.
-    if (tmp_term->type == LSUP_TERM_LITERAL)
+        else {
+            tmp_term = LSUP_lt_literal_new (term->data, (char *) term->lang);
+            memcpy (&metadata, tmp_term->lang, sizeof (metadata));
+        }
+    } else if (term->type == LSUP_TERM_LITERAL) {
+        tmp_term = LSUP_term_new (term->type, term->data, term->datatype);
         metadata = tmp_term->datatype;
-    else if (tmp_term->type == LSUP_TERM_LT_LITERAL)
-        memcpy (&metadata, tmp_term->lang, sizeof (metadata));
+    } else tmp_term = LSUP_term_copy (term);
 
     LSUP_Buffer *sterm;
     CALLOC_GUARD (sterm, NULL);
@@ -381,28 +363,16 @@ LSUP_term_free (LSUP_Term *term)
 {
     if (UNLIKELY (!term)) return;
 
-    if (LSUP_IS_IRI (term)) free (term->iri_info);
+    if (term->type == LSUP_TERM_IRIREF) free (term->iri_info);
     free (term->data);
     free (term);
 }
 
 
-LSUP_NSMap *
-LSUP_iriref_nsm (const LSUP_Term *iri)
-{
-    if (iri->type != LSUP_TERM_IRIREF && iri->type != LSUP_TERM_NS_IRIREF) {
-        log_error ("Term is not a IRI ref type.");
-        return NULL;
-    }
-
-    return iri->iri_info->nsm;
-}
-
-
 char *
 LSUP_iriref_prefix (const LSUP_Term *iri)
 {
-    if (iri->type != LSUP_TERM_IRIREF && iri->type != LSUP_TERM_NS_IRIREF) {
+    if (iri->type != LSUP_TERM_IRIREF) {
         log_error ("Term is not a IRI ref type.");
         return NULL;
     }
@@ -418,7 +388,7 @@ LSUP_iriref_prefix (const LSUP_Term *iri)
 char *
 LSUP_iriref_path (const LSUP_Term *iri)
 {
-    if (iri->type != LSUP_TERM_IRIREF && iri->type != LSUP_TERM_NS_IRIREF) {
+    if (iri->type != LSUP_TERM_IRIREF) {
         log_error ("Term is not a IRI ref type.");
         return NULL;
     }
@@ -434,7 +404,7 @@ LSUP_iriref_path (const LSUP_Term *iri)
 char *
 LSUP_iriref_frag (const LSUP_Term *iri)
 {
-    if (iri->type != LSUP_TERM_IRIREF && iri->type != LSUP_TERM_NS_IRIREF) {
+    if (iri->type != LSUP_TERM_IRIREF) {
         log_error ("Term is not a IRI ref type.");
         return NULL;
     }
@@ -792,18 +762,8 @@ term_init (
 
     if (data) {
         // Validate IRI.
-        if (LSUP_IS_IRI (term)) {
-            char *fquri;
-
-            // Find fully qualified IRI to parse.
-            if (term->type == LSUP_TERM_NS_IRIREF) {
-                if (LSUP_nsmap_normalize_uri (metadata, data, &fquri) < 0) {
-                    log_error ("Error normalizing IRI data.");
-                    return LSUP_VALUE_ERR;
-                }
-
-                LOG_DEBUG("Fully qualified IRI: %s", fquri);
-            } else fquri = (char *) data;
+        if (term->type == LSUP_TERM_IRIREF) {
+            char *fquri = (char *) data;
 
             if (strpbrk (fquri, invalid_uri_chars) != NULL) {
                 log_warn (
@@ -822,14 +782,11 @@ term_init (
 
                 return LSUP_VALUE_ERR;
             }
-            if (term->type == LSUP_TERM_NS_IRIREF) free (fquri);
-
             MALLOC_GUARD (term->iri_info, LSUP_MEM_ERR);
 
             term->iri_info->prefix = matches[1];
             term->iri_info->path = matches[4];
             term->iri_info->frag = matches[6];
-            term->iri_info->nsm = metadata;
         }
 
         term->data = strdup (data);
@@ -857,7 +814,6 @@ term_init (
                 term->iri_info->path.size = UUIDSTR_SIZE + 6;
                 term->iri_info->frag.offset = 0;
                 term->iri_info->frag.size = 0;
-                term->iri_info->nsm = NULL;
 
             } else term->data = strdup (uuid_str);
         } else {
@@ -889,7 +845,7 @@ term_init (
         if (! term->datatype) term->datatype = LSUP_default_datatype;
         LOG_TRACE("Storing data type: %s", term->datatype->data);
 
-        if (! LSUP_IS_IRI (term->datatype)) {
+        if (term->datatype->type != LSUP_TERM_IRIREF) {
             log_error (
                     "Literal data type is not an IRI: %s",
                     term->datatype->data);
@@ -1053,7 +1009,8 @@ parse_iri (char *iri_str, MatchCoord coord[]) {
  */
 
 LSUP_Key LSUP_term_hash (const LSUP_Term *term);
-LSUP_Term *LSUP_iriref_new (const char *data, LSUP_NSMap *nsm);
+LSUP_Term *LSUP_iriref_new (const char *data);
+LSUP_Term *LSUP_iriref_new_ns (const char *data);
 LSUP_Term *LSUP_literal_new (const char *data, LSUP_Term *datatype);
 LSUP_Term *LSUP_lt_literal_new (const char *data, char *lang);
 LSUP_Term *LSUP_bnode_new (const char *data);

+ 22 - 25
test/assets/triples.h

@@ -1,7 +1,7 @@
 #ifndef _TEST_ASSETS_TRIPLES_H
 #define _TEST_ASSETS_TRIPLES_H
 
-#include "term.h"
+#include "lsup/term.h"
 
 #define NUM_TRP 10
 
@@ -18,44 +18,43 @@
  */
 LSUP_Triple **create_triples()
 {
-    LSUP_NSMap *nsm = LSUP_nsmap_new ();
-    LSUP_nsmap_add (nsm, "ns1", "urn:s:");
-    LSUP_nsmap_add (nsm, "ns2", "urn:p:");
+    LSUP_nsmap_add ("ns1", "urn:s:");
+    LSUP_nsmap_add ("ns2", "urn:p:");
 
     LSUP_Term
-        *s0 = LSUP_iriref_new ("urn:s:0", NULL),
-        *s5 = LSUP_iriref_new ("ns1:0", nsm),
-        *p2 = LSUP_iriref_new ("urn:p:2", NULL),
-        *p4 = LSUP_iriref_new ("ns2:2", nsm),
+        *s0 = LSUP_iriref_new ("urn:s:0"),
+        *s5 = LSUP_iriref_new_ns ("ns1:0"),
+        *p2 = LSUP_iriref_new ("urn:p:2"),
+        *p4 = LSUP_iriref_new_ns ("ns2:2"),
         *o5 = LSUP_literal_new (
                     "String 1",
-                    LSUP_iriref_new ("urn:mydatatype:string", NULL));
+                    LSUP_iriref_new ("urn:mydatatype:string"));
 
     LSUP_Triple **trp = calloc (sizeof (*trp), NUM_TRP + 1);
     trp[0] = LSUP_triple_new (
             s0,
-            LSUP_iriref_new ("urn:p:0", NULL),
-            LSUP_iriref_new ("urn:o:0", NULL));
+            LSUP_iriref_new ("urn:p:0"),
+            LSUP_iriref_new ("urn:o:0"));
     trp[1] = LSUP_triple_new (
-            LSUP_iriref_new ("urn:s:1", NULL),
-            LSUP_iriref_new ("urn:p:1", NULL),
-            LSUP_iriref_new ("urn:o:1", NULL));
+            LSUP_iriref_new ("urn:s:1"),
+            LSUP_iriref_new ("urn:p:1"),
+            LSUP_iriref_new ("urn:o:1"));
     trp[2] = LSUP_triple_new (
-            LSUP_iriref_new ("urn:s:2", NULL),
+            LSUP_iriref_new ("urn:s:2"),
             p2,
-            LSUP_iriref_new ("urn:o:2", NULL));
+            LSUP_iriref_new ("urn:o:2"));
     trp[3] = LSUP_triple_new (
-            LSUP_iriref_new ("urn:s:0", NULL),
-            LSUP_iriref_new ("urn:p:1", NULL),
-            LSUP_iriref_new ("urn:o:2", NULL));
+            LSUP_iriref_new ("urn:s:0"),
+            LSUP_iriref_new ("urn:p:1"),
+            LSUP_iriref_new ("urn:o:2"));
     trp[4] = LSUP_triple_new (
-            LSUP_iriref_new ("urn:s:0", NULL),
+            LSUP_iriref_new ("urn:s:0"),
             p4,
             LSUP_literal_new ("String 1", NULL));
-    trp[5] = LSUP_triple_new (s5, LSUP_iriref_new ("urn:p:5", NULL), o5);
+    trp[5] = LSUP_triple_new (s5, LSUP_iriref_new ("urn:p:5"), o5);
     trp[6] = LSUP_triple_new (
-            LSUP_iriref_new ("urn:s:1", NULL),
-            LSUP_iriref_new ("urn:p:6", NULL),
+            LSUP_iriref_new ("urn:s:1"),
+            LSUP_iriref_new ("urn:p:6"),
             LSUP_lt_literal_new ("String 1", "es-ES"));
     // Unique triple from reused pointers. Do not double-free.
     trp[7] = LSUP_triple_new (s0, p2, o5);
@@ -71,8 +70,6 @@ LSUP_Triple **create_triples()
 
 void free_triples (LSUP_Triple **trp)
 {
-    LSUP_nsmap_free (LSUP_iriref_nsm (trp[4]->p));
-
     // Last three triples are second pointers.
     for (int i=0; i < NUM_TRP - 3; i++)
         LSUP_triple_free (trp[i]);

+ 12 - 14
test/test_codec_nt.c

@@ -11,15 +11,15 @@ LSUP_Term **
 init_terms (void)
 {
     LSUP_Term **terms = malloc (TERM_CT * sizeof (*terms));
-    terms[0] = LSUP_iriref_new("urn:local:s1", NULL);
-    terms[1] = LSUP_iriref_new("http://example.org/p1", NULL);
-    terms[2] = LSUP_iriref_new("http://example.org/p2", NULL);
+    terms[0] = LSUP_iriref_new("urn:local:s1");
+    terms[1] = LSUP_iriref_new("http://example.org/p1");
+    terms[2] = LSUP_iriref_new("http://example.org/p2");
     terms[3] = LSUP_literal_new ("hello", NULL);
     terms[4] = LSUP_lt_literal_new ("hello", "en-US");
     terms[5] = LSUP_lt_literal_new ("hello", "es-ES");
     terms[6] = LSUP_literal_new (
             "25",
-            LSUP_iriref_new ("http://www.w3.org/2001/XMLSchema#integer", NULL));
+            LSUP_iriref_new ("http://www.w3.org/2001/XMLSchema#integer"));
     terms[7] = LSUP_literal_new (
             "This \\is\\ a \"multi-line\"\n'literal'\t.", NULL);
     terms[8] = LSUP_bnode_new ("bn1");
@@ -131,28 +131,26 @@ test_encode_nt_term()
 {
     LSUP_Term **terms = init_terms();
 
-    LSUP_NSMap *nsm = LSUP_nsmap_new();
-    LSUP_nsmap_add (nsm, "local", "urn:local:");
-    LSUP_nsmap_add (nsm, "ext", "http://example.org");
+    LSUP_nsmap_add ("local", "urn:local:");
+    LSUP_nsmap_add ("ext", "http://example.org");
 
     char *out = NULL;
 
     // Test that passing a NS map has no effect.
-    EXPECT_PASS (codec.encode_term (terms[0], nsm, &out));
+    EXPECT_PASS (codec.encode_term (terms[0], &out));
     EXPECT_STR_EQ (out, end_nt[0]);
 
     for (int i = 0; i < TERM_CT - 2; i++) {
         log_info ("Test encoding term #%d of %d.", i, TERM_CT - 2);
-        EXPECT_PASS (codec.encode_term (terms[i], NULL, &out));
+        EXPECT_PASS (codec.encode_term (terms[i], &out));
         EXPECT_STR_EQ (out, end_nt[i]);
     }
 
-    EXPECT_INT_EQ (codec.encode_term (terms[9], NULL, &out), LSUP_PARSE_ERR);
+    EXPECT_INT_EQ (codec.encode_term (terms[9], &out), LSUP_PARSE_ERR);
 
-    EXPECT_INT_EQ (codec.encode_term (terms[10], NULL, &out), LSUP_PARSE_ERR);
+    EXPECT_INT_EQ (codec.encode_term (terms[10], &out), LSUP_PARSE_ERR);
 
     free (out);
-    LSUP_nsmap_free (nsm);
     free_terms (terms);
 
     return 0;
@@ -163,7 +161,7 @@ int
 test_encode_nt_graph()
 {
     log_info ("Test encoding graph document.");
-    LSUP_Graph *gr = LSUP_graph_new (NULL, NULL, NULL);
+    LSUP_Graph *gr = LSUP_graph_new (NULL, NULL);
     if (!gr) return LSUP_MEM_ERR;
 
     size_t ins;
@@ -201,7 +199,7 @@ test_decode_nt_term()
     for (int i = 0; i < TERM_CT - 2; i++) {
         LOG_DEBUG("Decoding term %d/%d.", i, TERM_CT - 3);
         LSUP_Term *term;
-        EXPECT_PASS (codec.decode_term (start_nt[i], NULL, &term));
+        EXPECT_PASS (codec.decode_term (start_nt[i], &term));
         LSUP_term_free (term);
     }
 

+ 1 - 1
test/test_codec_ttl.c

@@ -15,7 +15,7 @@ int
 test_encode_ttl_graph()
 {
     log_info ("Test encoding graph document.");
-    LSUP_Graph *gr = LSUP_graph_new (NULL, NULL, NULL);
+    LSUP_Graph *gr = LSUP_graph_new (NULL, NULL);
     if (!gr) return LSUP_MEM_ERR;
 
     size_t ins;

+ 40 - 43
test/test_graph.c

@@ -10,10 +10,10 @@ _graph_new (LSUP_StoreType type)
     LSUP_Graph *gr;
     LSUP_Store *store = NULL;
     if (type == LSUP_STORE_HTABLE) {
-        gr = LSUP_graph_new (NULL, NULL, NULL);
+        gr = LSUP_graph_new (NULL, NULL);
     } else {
         store = LSUP_store_new (type, NULL, 0, true);
-        gr = LSUP_graph_new (store, NULL, NULL);
+        gr = LSUP_graph_new (store, NULL);
     }
     ASSERT (gr != NULL, "Error creating graph!");
 
@@ -56,25 +56,22 @@ _graph_ns_uri (LSUP_StoreType type)
 
     log_info("Testing NSM for graph store type: %d", type);
 
-    LSUP_NSMap *nsm = LSUP_nsmap_new();
     for (int i = 0; nsdata[i][0]; i++)
-        EXPECT_PASS (LSUP_nsmap_add (nsm, nsdata[i][0], nsdata[i][1]));
+        EXPECT_PASS (LSUP_nsmap_add (nsdata[i][0], nsdata[i][1]));
 
-    LSUP_Graph *gr = LSUP_graph_new (store, "ns1:gr1", nsm);
+    LSUP_Graph *gr;
+    gr = LSUP_graph_new_ns (store, NULL);
+    ASSERT (gr == NULL, "NS graph URI cannot be NULL!");
+    gr = LSUP_graph_new_ns (store, "ns1:gr1");
     ASSERT (gr != NULL, "Error creating graph!");
 
-    ASSERT (
-            LSUP_graph_uri (gr)->type == LSUP_TERM_NS_IRIREF,
-            "Namespace prefixing failed!");
-
-    LSUP_Term *comp = LSUP_iriref_new ("urn:ns1#gr1", NULL);
+    LSUP_Term *comp = LSUP_iriref_new ("urn:ns1#gr1");
     ASSERT (
             LSUP_term_equals (LSUP_graph_uri (gr), comp),
             "Namespaced graph URI is incorrect!" );
     LSUP_term_free (comp);
 
     LSUP_graph_free (gr);
-    LSUP_nsmap_free (nsm);
     LSUP_store_free (store);
 
     return 0;
@@ -91,7 +88,7 @@ _graph_add (LSUP_StoreType type)
     if (type == LSUP_STORE_HTABLE) store = NULL;
     else store = LSUP_store_new (type, NULL, 0, true);
 
-    gr = LSUP_graph_new (store, NULL, NULL);
+    gr = LSUP_graph_new (store, NULL);
     ASSERT (gr != NULL, "Error creating graph!");
 
     size_t ct;
@@ -115,7 +112,7 @@ _graph_add (LSUP_StoreType type)
     // Check size again after freeing triples.
     EXPECT_INT_EQ (LSUP_graph_size (gr), 8);
 
-    LSUP_Graph *gr2 = LSUP_graph_new (NULL, NULL, NULL);
+    LSUP_Graph *gr2 = LSUP_graph_new (NULL, NULL);
 
     // Test equality against empty graph.
     ASSERT (!LSUP_graph_equals (gr, gr2), "Graphs should not be equal!");
@@ -142,8 +139,8 @@ _graph_get (LSUP_StoreType type)
     if (type == LSUP_STORE_HTABLE) store = NULL;
     else store = LSUP_store_new (type, NULL, 0, true);
     LSUP_Graph
-        *gr1 = LSUP_graph_new (store, NULL, NULL),
-        *gr2 = LSUP_graph_new (store, NULL, NULL);
+        *gr1 = LSUP_graph_new (store, NULL),
+        *gr2 = LSUP_graph_new (store, NULL);
 
     ASSERT (gr1 != NULL, "Error creating graph!");
     ASSERT (gr2 != NULL, "Error creating graph!");
@@ -198,7 +195,7 @@ _graph_link_map (LSUP_StoreType type)
     LSUP_Store *store;
     if (type == LSUP_STORE_HTABLE) store = NULL;
     else store = LSUP_store_new (type, NULL, 0, true);
-    LSUP_Graph *gr = LSUP_graph_new (store, NULL, NULL);
+    LSUP_Graph *gr = LSUP_graph_new (store, NULL);
 
     size_t ct;
     LSUP_graph_add (gr, trp, &ct);
@@ -320,8 +317,8 @@ _graph_bool_ops (LSUP_StoreType type)
     if (type == LSUP_STORE_HTABLE) store = NULL;
     else store = LSUP_store_new (type, NULL, 0, true);
     LSUP_Graph
-        *gr1 = LSUP_graph_new (store, NULL, NULL),
-        *gr2 = LSUP_graph_new (store, NULL, NULL),
+        *gr1 = LSUP_graph_new (store, NULL),
+        *gr2 = LSUP_graph_new (store, NULL),
         *gr_dest;
 
     // Add 2 groups of triples to different graphs.
@@ -342,14 +339,14 @@ _graph_bool_ops (LSUP_StoreType type)
     LSUP_graph_add_done (it);
 
     // Test union.
-    gr_dest = LSUP_graph_new (store, NULL, NULL);
+    gr_dest = LSUP_graph_new (store, NULL);
     EXPECT_PASS (LSUP_graph_bool_op (LSUP_BOOL_UNION, gr1, gr2, gr_dest));
     for (size_t i = 0; i < 8; i++)
         ASSERT (LSUP_graph_contains (gr_dest, trp[i]), "Union test failed!");
     LSUP_graph_free (gr_dest);
 
     // Test subtraction.
-    gr_dest = LSUP_graph_new (store, NULL, NULL);
+    gr_dest = LSUP_graph_new (store, NULL);
     EXPECT_PASS (LSUP_graph_bool_op (
                 LSUP_BOOL_SUBTRACTION, gr1, gr2, gr_dest));
     for (size_t i = 0; i < 3; i++)
@@ -360,7 +357,7 @@ _graph_bool_ops (LSUP_StoreType type)
                     gr_dest, trp[i]), "Subtraction test has excess triples!");
     LSUP_graph_free (gr_dest);
 
-    gr_dest = LSUP_graph_new (store, NULL, NULL);
+    gr_dest = LSUP_graph_new (store, NULL);
     EXPECT_PASS (LSUP_graph_bool_op (
                 LSUP_BOOL_SUBTRACTION, gr2, gr1, gr_dest));
     for (size_t i = 0; i < 4; i++)
@@ -372,7 +369,7 @@ _graph_bool_ops (LSUP_StoreType type)
     LSUP_graph_free (gr_dest);
 
     // Test intersection.
-    gr_dest = LSUP_graph_new (store, NULL, NULL);
+    gr_dest = LSUP_graph_new (store, NULL);
     EXPECT_PASS (LSUP_graph_bool_op (
                 LSUP_BOOL_INTERSECTION, gr1, gr2, gr_dest));
     for (size_t i = 0; i < 3; i++)
@@ -386,7 +383,7 @@ _graph_bool_ops (LSUP_StoreType type)
     LSUP_graph_free (gr_dest);
 
     // Test XOR.
-    gr_dest = LSUP_graph_new (store, NULL, NULL);
+    gr_dest = LSUP_graph_new (store, NULL);
     EXPECT_PASS (LSUP_graph_bool_op (LSUP_BOOL_XOR, gr1, gr2, gr_dest));
     for (size_t i = 0; i < 3; i++)
         ASSERT (LSUP_graph_contains (
@@ -466,10 +463,10 @@ _graph_lookup (LSUP_StoreType type)
     LSUP_Graph *gr;
     LSUP_Store *store = NULL;
     if (type == LSUP_STORE_HTABLE) {
-        gr = LSUP_graph_new (NULL, NULL, NULL);
+        gr = LSUP_graph_new (NULL, NULL);
     } else {
         store = LSUP_store_new (type, NULL, 0, true);
-        gr = LSUP_graph_new (store, NULL, NULL);
+        gr = LSUP_graph_new (store, NULL);
     }
 
     size_t ct;
@@ -534,10 +531,10 @@ _graph_remove (LSUP_StoreType type)
     LSUP_Graph *gr;
     LSUP_Store *store = NULL;
     if (type == LSUP_STORE_HTABLE) {
-        gr = LSUP_graph_new (NULL, NULL, NULL);
+        gr = LSUP_graph_new (NULL, NULL);
     } else {
         store = LSUP_store_new (type, NULL, 0, true);
-        gr = LSUP_graph_new (store, NULL, NULL);
+        gr = LSUP_graph_new (store, NULL);
     }
 
     size_t ct;
@@ -585,7 +582,7 @@ _graph_txn (LSUP_StoreType type)
         type == LSUP_STORE_HTABLE ? NULL
         : LSUP_store_new (type, NULL, 0, true);
 
-    gr = LSUP_graph_new (store, NULL, NULL);
+    gr = LSUP_graph_new (store, NULL);
 
     void *txn;
     size_t ct;
@@ -619,14 +616,14 @@ static int
 _graph_relative (LSUP_StoreType type)
 {
     LSUP_Term
-        *s = LSUP_iriref_new ("http://onto.knowledgetx.com/gr1/s1", NULL),
-        *s2 = LSUP_iriref_new ("http://onto.knowledgetx.com/gr2/s1", NULL),
-        *p = LSUP_iriref_new ("http://onto.knowledgetx.com/vocab/p1", NULL),
-        *o = LSUP_iriref_new ("http://onto.knowledgetx.com/gr1/o1", NULL),
-        *o2 = LSUP_iriref_new ("http://onto.knowledgetx.com/gr2/o1", NULL),
-        *c = LSUP_iriref_new ("http://onto.knowledgetx.com/gr1/", NULL),
-        *rel_s = LSUP_iriref_relative (c, s),
-        *rel_o = LSUP_iriref_relative (c, o);
+        *s = LSUP_iriref_new ("http://onto.knowledgetx.com/gr1/s1"),
+        *s2 = LSUP_iriref_new ("http://onto.knowledgetx.com/gr2/s1"),
+        *p = LSUP_iriref_new ("http://onto.knowledgetx.com/vocab/p1"),
+        *o = LSUP_iriref_new ("http://onto.knowledgetx.com/gr1/o1"),
+        *o2 = LSUP_iriref_new ("http://onto.knowledgetx.com/gr2/o1"),
+        *c = LSUP_iriref_new ("http://onto.knowledgetx.com/gr1/"),
+        *rel_s = LSUP_iriref_new_rel (c, s),
+        *rel_o = LSUP_iriref_new_rel (c, o);
     LSUP_Triple *spo[2] = {
         LSUP_triple_new (s, p, o),
         NULL
@@ -637,7 +634,7 @@ _graph_relative (LSUP_StoreType type)
         type == LSUP_STORE_HTABLE ? NULL
         : LSUP_store_new (type, NULL, 0, true);
 
-    LSUP_Graph *gr = LSUP_graph_new (store, c->data, NULL);
+    LSUP_Graph *gr = LSUP_graph_new (store, c->data);
 
     size_t ct;
     LSUP_graph_add (gr, spo, &ct);
@@ -679,9 +676,9 @@ _graph_list (LSUP_StoreType type)
     LSUP_Store *store = LSUP_store_new (type, NULL, 0, true);
 
     LSUP_Graph *gg[3] = {
-        LSUP_graph_new (store,  "urn:gr:1", NULL),
-        LSUP_graph_new (store,  "urn:gr:2", NULL),
-        LSUP_graph_new (store,  "urn:gr:3", NULL),
+        LSUP_graph_new (store,  "urn:gr:1"),
+        LSUP_graph_new (store,  "urn:gr:2"),
+        LSUP_graph_new (store,  "urn:gr:3"),
     };
 
     LSUP_Triple **trp = create_triples();
@@ -862,13 +859,13 @@ static int test_graph_copy()
 {
     LSUP_Triple **trp = create_triples();
 
-    LSUP_Graph *gr1 = LSUP_graph_new (NULL, NULL, NULL);
+    LSUP_Graph *gr1 = LSUP_graph_new (NULL, NULL);
     ASSERT (gr1 != NULL, "Error creating graph!");
 
     LSUP_graph_add (gr1, trp, NULL);
 
     // Copy to graph with same store type.
-    LSUP_Graph *gr2 = LSUP_graph_new (NULL, NULL, NULL);
+    LSUP_Graph *gr2 = LSUP_graph_new (NULL, NULL);
     EXPECT_PASS (LSUP_graph_copy_contents (gr1, gr2, NULL, NULL, NULL));
     EXPECT_INT_EQ (LSUP_graph_size (gr1), LSUP_graph_size (gr2));
 
@@ -880,7 +877,7 @@ static int test_graph_copy()
     }
 
     // Copy to graph with a different store type.
-    LSUP_Graph *gr3 = LSUP_graph_new (NULL, NULL, NULL);
+    LSUP_Graph *gr3 = LSUP_graph_new (NULL, NULL);
     EXPECT_PASS (LSUP_graph_copy_contents (gr1, gr3, NULL, NULL, NULL));
     EXPECT_INT_EQ (LSUP_graph_size (gr1), LSUP_graph_size (gr2));
 

+ 38 - 28
test/test_namespace.c

@@ -4,67 +4,77 @@
 static int
 test_namespace()
 {
-    LSUP_NSMap *nsm = LSUP_nsmap_new();
-    ASSERT (nsm != NULL, "Error creating namespace map!");
+    // Use nonconventional prefix names to avoid clashes with default
+    // namespace prefixes already registered.
+
+    ASSERT (LSUP_default_nsm != NULL, "Error creating namespace map on init!");
 
     EXPECT_PASS (
-            LSUP_nsmap_add (nsm, "dc", "http://purl.org/dc/elements/1.1/"));
-    EXPECT_PASS (LSUP_nsmap_add (nsm, "dcterms", "http://purl.org/dc/terms/"));
+            LSUP_nsmap_add ("tdc", "http://purl.org/dc/elements/1.1/"));
+    EXPECT_PASS (LSUP_nsmap_add ("tdcterms", "http://purl.org/dc/terms/"));
+    EXPECT_PASS (LSUP_nsmap_add ("ns1", "urn:ns1:"));
+    EXPECT_PASS (LSUP_nsmap_add ("ns2", "urn:ns2:"));
 
     // Look up prefix.
     EXPECT_STR_EQ (
-            LSUP_nsmap_get_ns (nsm, "dc"), "http://purl.org/dc/elements/1.1/");
+            LSUP_nsmap_get_ns ("tdc"), "http://purl.org/dc/elements/1.1/");
     EXPECT_STR_EQ (
-            LSUP_nsmap_get_ns (nsm, "dcterms"), "http://purl.org/dc/terms/");
+            LSUP_nsmap_get_ns ("tdcterms"), "http://purl.org/dc/terms/");
     // Prefixes longer than 7 chars are truncated.
     EXPECT_STR_EQ (
-            LSUP_nsmap_get_ns (nsm, "dctermsxx"), "http://purl.org/dc/terms/");
-    ASSERT (LSUP_nsmap_get_ns (nsm, "none") == NULL, "Non-existent NS found!");
+            LSUP_nsmap_get_ns ("dctermsxx"), "http://purl.org/dc/terms/");
+    ASSERT (LSUP_nsmap_get_ns ("none") == NULL, "Non-existent NS found!");
 
     // Lookup NS.
-    EXPECT_STR_EQ (
-            LSUP_nsmap_get_pfx (nsm, "http://purl.org/dc/elements/1.1/"), "dc");
-    EXPECT_STR_EQ (
-            LSUP_nsmap_get_pfx (nsm, "http://purl.org/dc/terms/"), "dcterms");
+    EXPECT_STR_EQ (LSUP_nsmap_get_pfx ("urn:ns1:"), "ns1");
+    EXPECT_STR_EQ (LSUP_nsmap_get_pfx ("urn:ns2:"), "ns2");
+    // Cannot test tdc and tdcterms reverse lookup because dc and dcterms are
+    // also mapped to the same ns, and either one can come up.
 
     // Normalize and denormalize URIs.
     char *fq_uri, *pfx_uri;
-    fq_uri = "http://purl.org/dc/elements/1.1/title";
+    fq_uri = "urn:ns1:res1";
 
-    EXPECT_PASS (LSUP_nsmap_denormalize_uri (nsm, fq_uri, &pfx_uri));
-    EXPECT_STR_EQ (pfx_uri, "dc:title");
+    EXPECT_PASS (LSUP_nsmap_denormalize_uri (fq_uri, &pfx_uri));
+    EXPECT_STR_EQ (pfx_uri, "ns1:res1");
 
     fq_uri = NULL;
-    EXPECT_PASS (LSUP_nsmap_normalize_uri (nsm, pfx_uri, &fq_uri));
-    EXPECT_STR_EQ (fq_uri, "http://purl.org/dc/elements/1.1/title");
+    EXPECT_PASS (LSUP_nsmap_normalize_uri (pfx_uri, &fq_uri));
+    EXPECT_STR_EQ (fq_uri, "urn:ns1:res1");
     free (fq_uri);
+    free (pfx_uri);
 
     ASSERT (
-            LSUP_nsmap_normalize_uri (nsm, "dctermsxxtitle", &fq_uri)
+            LSUP_nsmap_normalize_uri ("dctermsxxtitle", &fq_uri)
             == LSUP_NORESULT, "Wrong RC for normalizing long ns!");
-    EXPECT_STR_EQ (fq_uri, "dctermsxxtitle");
+    ASSERT (!fq_uri, "Faulty normalization output should be NULL!");
     free (fq_uri);
 
     ASSERT (
-            LSUP_nsmap_normalize_uri (nsm, "bogus:ns:123", &fq_uri)
+            LSUP_nsmap_normalize_uri ("bogus:ns:123", &fq_uri)
             == LSUP_NORESULT, "Wrong RC for normalizing non-existent ns!");
-    EXPECT_STR_EQ (fq_uri, "bogus:ns:123");
+    ASSERT (!fq_uri, "Faulty normalization output should be NULL!");
     free (fq_uri);
 
     ASSERT (
-            LSUP_nsmap_normalize_uri (nsm, "bogus", &fq_uri)
+            LSUP_nsmap_normalize_uri ("bogus", &fq_uri)
             == LSUP_NORESULT, "Wrong RC for normalizing non-prefixed URI!");
-    EXPECT_STR_EQ (fq_uri, "bogus");
+    ASSERT (!fq_uri, "Faulty normalization output should be NULL!");
     free (fq_uri);
 
-    EXPECT_PASS (LSUP_nsmap_remove (nsm, "dc"));
+    EXPECT_PASS (LSUP_nsmap_remove ("tdc"));
+    ASSERT (LSUP_nsmap_get_ns ("tdc") == NULL, "Deleted NS found!");
+
     ASSERT (
-            LSUP_nsmap_remove (nsm, "none") == LSUP_NOACTION,
+            LSUP_nsmap_remove ("none") == LSUP_NOACTION,
             "Wrong result for removal of non-existent prefix!");
-    ASSERT (LSUP_nsmap_get_ns (nsm, "dc") == NULL, "Deleted NS found!");
 
-    LSUP_nsmap_free (nsm);
-    free (pfx_uri);
+    // Test normalization after removal.
+    ASSERT (
+            LSUP_nsmap_normalize_uri ("tdc:title", &fq_uri)
+            == LSUP_NORESULT, "Wrong RC for normalizing non-prefixed URI!");
+    ASSERT (!fq_uri, "Faulty normalization output should be NULL!");
+    free (fq_uri);
 
     return 0;
 }

+ 2 - 2
test/test_store.c

@@ -164,7 +164,7 @@ static int test_quad_store()
 
     LSUP_Buffer *sc1 = LSUP_default_ctx_buf;
 
-    LSUP_Term *ctx2 = LSUP_iriref_new("urn:c:2", NULL);
+    LSUP_Term *ctx2 = LSUP_iriref_new("urn:c:2");
     LSUP_Buffer *sc2 = LSUP_term_serialize (ctx2);
 
     // Only triples 4÷9 in context 2 (effectively 4 non-duplicates).
@@ -184,7 +184,7 @@ static int test_quad_store()
     EXPECT_INT_EQ (LSUP_store_size (store), 10);
 
     // This context has no triples.
-    LSUP_Term *ctx3 = LSUP_iriref_new("urn:c:3", NULL);
+    LSUP_Term *ctx3 = LSUP_iriref_new("urn:c:3");
     LSUP_Buffer *sc3 = LSUP_term_serialize (ctx3);
 
     // Test lookups.

+ 4 - 4
test/test_store_mdb.c

@@ -21,8 +21,8 @@ static int test_ctx_switch()
     size_t num_trp = (getpagesize() * 2 / TRP_KLEN) + 4;
     LSUP_BufferTriple **tdata = malloc (num_trp * sizeof (*tdata));
     LSUP_Triple *trp = LSUP_triple_new (
-        LSUP_iriref_new ("urn:s:1", NULL),
-        LSUP_iriref_new ("urn:p:1", NULL),
+        LSUP_iriref_new ("urn:s:1"),
+        LSUP_iriref_new ("urn:p:1"),
         NULL);
     char *o_str = malloc (8 * sizeof (*o_str));
     if (UNLIKELY (!o_str)) return LSUP_MEM_ERR;
@@ -38,8 +38,8 @@ static int test_ctx_switch()
     LOG_DEBUG ("Created %lu triples.", num_trp);
 
     LSUP_Term
-        *c1 = LSUP_iriref_new ("urn:c:1", NULL),
-        *c2 = LSUP_iriref_new ("urn:c:2", NULL);
+        *c1 = LSUP_iriref_new ("urn:c:1"),
+        *c2 = LSUP_iriref_new ("urn:c:2");
     LSUP_Buffer
         *sc1 = LSUP_term_serialize (c1),
         *sc2 = LSUP_term_serialize (c2);

+ 30 - 42
test/test_term.c

@@ -7,15 +7,11 @@ static int test_iriref()
     char *uri2_data = "ns1:12345";
     char *uri3_data = "ns2:12345";
 
-    LSUP_NSMap *nsm1 = LSUP_nsmap_new();
-    LSUP_nsmap_add (nsm1, "ns1", "http://example.org/term#");
+    LSUP_nsmap_add ("ns1", "http://example.org/term#");
+    LSUP_nsmap_add ("ns2", "http://example.org/term#");
 
-    LSUP_NSMap *nsm2 = LSUP_nsmap_new();
-    LSUP_nsmap_add (nsm2, "ns2", "http://example.org/term#");
-
-    LSUP_Term *uri1 = LSUP_iriref_new (uri1_data, NULL);
+    LSUP_Term *uri1 = LSUP_iriref_new (uri1_data);
     ASSERT (uri1, "IRI is NULL!");
-    ASSERT (LSUP_iriref_nsm (uri1) == NULL, "Wrong NSMap!");
     char *pfx = LSUP_iriref_prefix (uri1);
     char *path = LSUP_iriref_path (uri1);
     char *frag = LSUP_iriref_frag (uri1);
@@ -26,23 +22,21 @@ static int test_iriref()
     free (path);
     free (frag);
 
-    LSUP_Term *uri2 = LSUP_iriref_new (uri2_data, nsm1);
+    LSUP_Term *uri2 = LSUP_iriref_new_ns (uri2_data);
     ASSERT (uri2, "IRI is NULL!");
-    ASSERT (LSUP_iriref_nsm (uri2) == nsm1, "Wrong NSMap!");
 
-    LSUP_Term *uri3 = LSUP_iriref_new (uri3_data, nsm2);
+    LSUP_Term *uri3 = LSUP_iriref_new_ns (uri3_data);
     ASSERT (uri3, "IRI is NULL!");
-    ASSERT (LSUP_iriref_nsm (uri3) == nsm2, "Wrong NSMap!");
 
-    LSUP_Term *uri4 = LSUP_iriref_new (NULL, NULL);
+    LSUP_Term *uri4 = LSUP_iriref_new (NULL);
     ASSERT (uri4, "IRI is NULL!");
 
-    LSUP_Term *uri5 = LSUP_iriref_new (NULL, NULL);
+    LSUP_Term *uri5 = LSUP_iriref_new (NULL);
     ASSERT (uri5, "IRI is NULL!");
 
     EXPECT_INT_EQ (uri1->type, LSUP_TERM_IRIREF);
-    EXPECT_INT_EQ (uri2->type, LSUP_TERM_NS_IRIREF);
-    EXPECT_INT_EQ (uri3->type, LSUP_TERM_NS_IRIREF);
+    EXPECT_INT_EQ (uri2->type, LSUP_TERM_IRIREF);
+    EXPECT_INT_EQ (uri3->type, LSUP_TERM_IRIREF);
     EXPECT_INT_EQ (uri4->type, LSUP_TERM_IRIREF);
     EXPECT_INT_EQ (uri5->type, LSUP_TERM_IRIREF);
 
@@ -56,8 +50,6 @@ static int test_iriref()
     LSUP_term_free (uri3);
     LSUP_term_free (uri4);
     LSUP_term_free (uri5);
-    LSUP_nsmap_free (nsm1);
-    LSUP_nsmap_free (nsm2);
 
     return 0;
 }
@@ -102,7 +94,7 @@ static int test_iriref_parts()
     };
 
     for (size_t i = 0; i < 18; i++) {
-        LSUP_Term *iri = LSUP_iriref_new(data[i][0], NULL);
+        LSUP_Term *iri = LSUP_iriref_new(data[i][0]);
         char
             *pfx = LSUP_iriref_prefix (iri),
             *path = LSUP_iriref_path (iri),
@@ -123,27 +115,26 @@ static int test_iriref_parts()
 
 static int test_iriref_abs_rel()
 {
-    LSUP_NSMap *nsm1 = LSUP_nsmap_new();
-    LSUP_nsmap_add (nsm1, "ns1", "http://example.org/res/");
+    EXPECT_PASS (LSUP_nsmap_add ("ns1", "http://example.org/res/"));
 
-    LSUP_Term *root1 = LSUP_iriref_new ("http://example.org/res/", NULL);
-    LSUP_Term *root2 = LSUP_iriref_new ("urn:id:", NULL);
+    LSUP_Term *root1 = LSUP_iriref_new ("http://example.org/res/");
+    LSUP_Term *root2 = LSUP_iriref_new ("urn:id:");
 
-    LSUP_Term *rel_iri1 = LSUP_iriref_new ("http://anotherex.net/res/25", NULL);
-    LSUP_Term *rel_iri2 = LSUP_iriref_new ("/admin/32", NULL);
-    LSUP_Term *rel_iri3 = LSUP_iriref_new ("45/678", NULL);
+    LSUP_Term *rel_iri1 = LSUP_iriref_new ("http://anotherex.net/res/25");
+    LSUP_Term *rel_iri2 = LSUP_iriref_new ("/admin/32");
+    LSUP_Term *rel_iri3 = LSUP_iriref_new ("45/678");
 
-    LSUP_Term *abs_iri1 = LSUP_iriref_absolute (root1, rel_iri1);
-    LSUP_Term *abs_iri2 = LSUP_iriref_absolute (root1, rel_iri2);
-    LSUP_Term *abs_iri3 = LSUP_iriref_absolute (root1, rel_iri3);
+    LSUP_Term *abs_iri1 = LSUP_iriref_new_abs (root1, rel_iri1);
+    LSUP_Term *abs_iri2 = LSUP_iriref_new_abs (root1, rel_iri2);
+    LSUP_Term *abs_iri3 = LSUP_iriref_new_abs (root1, rel_iri3);
 
     EXPECT_STR_EQ (abs_iri1->data, rel_iri1->data);
     EXPECT_STR_EQ (abs_iri2->data, "http://example.org/admin/32");
     EXPECT_STR_EQ (abs_iri3->data, "http://example.org/res/45/678");
 
-    LSUP_Term *rel_iri1a = LSUP_iriref_relative (root1, abs_iri1);
-    LSUP_Term *rel_iri2a = LSUP_iriref_relative (root1, abs_iri2);
-    LSUP_Term *rel_iri3a = LSUP_iriref_relative (root1, abs_iri3);
+    LSUP_Term *rel_iri1a = LSUP_iriref_new_rel (root1, abs_iri1);
+    LSUP_Term *rel_iri2a = LSUP_iriref_new_rel (root1, abs_iri2);
+    LSUP_Term *rel_iri3a = LSUP_iriref_new_rel (root1, abs_iri3);
 
     EXPECT_STR_EQ (rel_iri1a->data, rel_iri1->data);
     EXPECT_STR_EQ (rel_iri2a->data, abs_iri2->data);
@@ -160,7 +151,6 @@ static int test_iriref_abs_rel()
     LSUP_term_free (rel_iri1a);
     LSUP_term_free (rel_iri2a);
     LSUP_term_free (rel_iri3a);
-    LSUP_nsmap_free (nsm1);
 
     return 0;
 }
@@ -172,7 +162,7 @@ static int test_literal()
     char *datatype = "urn:my:datatype";
     char *lang = "en-US";
 
-    LSUP_Term *lit1 = LSUP_literal_new (data, LSUP_iriref_new (datatype, NULL));
+    LSUP_Term *lit1 = LSUP_literal_new (data, LSUP_iriref_new (datatype));
     EXPECT_INT_EQ (lit1->type, LSUP_TERM_LITERAL);
     EXPECT_STR_EQ (lit1->data, data);
     EXPECT_STR_EQ (lit1->datatype->data, datatype);
@@ -233,10 +223,10 @@ static int test_undefined()
 
 static int test_term_copy()
 {
-    LSUP_Term *uri1 = LSUP_iriref_new ("http://hello.org", NULL);
+    LSUP_Term *uri1 = LSUP_iriref_new ("http://hello.org");
     LSUP_Term *lit1 = LSUP_literal_new ("hello", NULL);
     LSUP_Term *tlit1 = LSUP_literal_new (
-            "hello", LSUP_iriref_new ("urn:mydatatype:string", NULL));
+            "hello", LSUP_iriref_new ("urn:mydatatype:string"));
     LSUP_Term *llit1 = LSUP_lt_literal_new ("hello", "en-US");
 
     LSUP_Term *uri2 = LSUP_term_copy (uri1);
@@ -263,10 +253,10 @@ static int test_term_copy()
 
 static int test_term_serialize_deserialize()
 {
-    LSUP_Term *uri = LSUP_iriref_new ("http://hello.org", NULL);
+    LSUP_Term *uri = LSUP_iriref_new ("http://hello.org");
     LSUP_Term *lit = LSUP_literal_new ("hello", NULL);
     LSUP_Term *tlit = LSUP_literal_new (
-            "hello", LSUP_iriref_new ("urn:mydatatype:string", NULL));
+            "hello", LSUP_iriref_new ("urn:mydatatype:string"));
     LSUP_Term *llit = LSUP_lt_literal_new ("hello", "en-US");
 
     LSUP_Buffer *sterm;
@@ -326,11 +316,10 @@ static int test_term_serialize_deserialize()
 
 static int test_term_to_key()
 {
-    LSUP_NSMap *nsm = LSUP_nsmap_new();
-    LSUP_nsmap_add (nsm, "ns1", "http://hello.org/term#");
+    LSUP_nsmap_add ("ns1", "http://hello.org/term#");
 
-    LSUP_Term *uri1 = LSUP_iriref_new ("http://hello.org/term#bye", NULL);
-    LSUP_Term *uri2 = LSUP_iriref_new ("ns1:bye", nsm);
+    LSUP_Term *uri1 = LSUP_iriref_new ("http://hello.org/term#bye");
+    LSUP_Term *uri2 = LSUP_iriref_new_ns ("ns1:bye");
     LSUP_Term *lit = LSUP_literal_new ("hello", NULL);
     LSUP_Term *tlit = LSUP_literal_new ("hello", LSUP_default_datatype);
     LSUP_Term *llit1 = LSUP_lt_literal_new ("hello", "en-US");
@@ -360,7 +349,6 @@ static int test_term_to_key()
     LSUP_term_free (llit1);
     LSUP_term_free (llit2);
     LSUP_term_free (llit3);
-    LSUP_nsmap_free (nsm);
 
     return 0;
 }