Browse Source

WIP: sstabilize API.

Stefano Cossu 3 years ago
parent
commit
16437aa26b
19 changed files with 511 additions and 485 deletions
  1. 28 34
      Makefile
  2. 97 12
      include/buffer.h
  3. 4 1
      include/core.h
  4. 8 40
      include/graph.h
  5. 23 25
      include/store_htable.h
  6. 7 9
      include/store_mdb.h
  7. 54 16
      include/term.h
  8. 0 8
      include/triple.h
  9. 23 41
      src/buffer.c
  10. 58 95
      src/graph.c
  11. 37 39
      src/store_htable.c
  12. 34 41
      src/store_mdb.c
  13. 53 27
      src/term.c
  14. 9 9
      src/triple.c
  15. 26 26
      test/assets.h
  16. 2 3
      test/test_graph.c
  17. 18 18
      test/test_htable.c
  18. 11 15
      test/test_store_mdb.c
  19. 19 26
      test/test_term.c

+ 28 - 34
Makefile

@@ -1,48 +1,42 @@
-.PHONY: build test profile
+CC=gcc
+CFLAGS+= -Wall -std=c99 -D_XOPEN_SOURCE=500
+INCLUDE=-Iinclude -Iext/xxHash -Iext/openldap/libraries/liblmdb
+LIB=-luuid -lpthread
+SRC=ext/xxHash/xxhash.c ext/openldap/libraries/liblmdb/mdb.c \
+	ext/openldap/libraries/liblmdb/midl.c src/*.c
 
-default: all
+.PHONY: build test lint profile
 
-all: test
+default: test
 
-check:
+build:
+	$(CC) \
+		$(CFLAGS) -Werror
+		$(INCLUDE) \
+		$(LIB) \
+		$(SRC) \
+		-o bin/lsup_rdf.so
+
+lint:
 	splint \
-		-Iinclude -Iext/xxHash -Iext/openldap/libraries/liblmdb -Itest \
-		-D_XOPEN_SOURCE=500 \
+		$(INCLUDE) -Itest \
 		-DUINT_MAX=0xFFFFFFFFUL \
 		-nullpass \
 		-posix-lib \
 		test.c
 
-build:
-	gcc -g -Wall \
-		-std=c99 \
-		-Iinclude -Iext/xxHash -Iext/openldap/libraries/liblmdb \
-		-luuid -lpthread \
-		-D_XOPEN_SOURCE=500 \
-		ext/xxHash/xxhash.c ext/openldap/libraries/liblmdb/midl.c \
-		ext/openldap/libraries/liblmdb/mdb.c \
-		src/*.c \
-		-o bin/lsup_rdf.so
-
 test:
-	gcc -g -Wall \
-		-std=c99 \
-		-DDEBUG \
-		-Iinclude -Iext/xxHash -Iext/openldap/libraries/liblmdb -Itest \
-		-luuid -lpthread \
-		-D_XOPEN_SOURCE=500 \
-		ext/xxHash/xxhash.c ext/openldap/libraries/liblmdb/midl.c \
-		ext/openldap/libraries/liblmdb/mdb.c \
-		src/*.c test.c \
+	$(CC) \
+		$(CFLAGS) -g3 -DDEBUG \
+		$(INCLUDE) -Itest \
+		$(LIB) \
+		$(SRC) test.c \
 		-o bin/test
 
 profile:
-	gcc -g -Wall \
-		-std=c99 \
-		-Iinclude -Iext/xxHash -Iext/openldap/libraries/liblmdb \
-		-luuid \
-		-D_XOPEN_SOURCE=500 \
-		ext/xxHash/xxhash.c ext/openldap/libraries/liblmdb/midl.c \
-		ext/openldap/libraries/liblmdb/mdb.c \
-		src/*.c profile.c \
+	$(CC) \
+		$(CFLAGS)
+		$(INCLUDE) \
+		$(LIB) \
+		$(SRC) profile.c \
 		-o bin/profile

+ 97 - 12
include/buffer.h

@@ -3,32 +3,117 @@
 
 #include "core.h"
 
+/** @brief General-purpose data buffer.
+ *
+ * The structure is transparently exposed so that the related API only defines
+ * few basic helper methods. Other operations, such as appending, may be
+ * performed by simply using the addr and size attributes.
+ *
+ * A buffer can be initialized once and reused multiple times, e.g. in a loop,
+ * without being freed between iterations, by using #LSUP_buffer_reset.
+ */
 typedef struct LSUP_Buffer {
-    void *addr;
+    /*@null@*/ void *addr;
     size_t size;
 } LSUP_Buffer;
 
 
+/** Reuse an initialized buffer handle.
+ *
+ * The data block is resized without being freed (with realloc). If the new
+ * size is not smaller than the old one and the data parameter is NULL, the
+ * existing data are preserved. If the size is increased, the new memory is not
+ * initialized.
+ *
+ * The handle must be freed with #LSUP_buffer_done after use.
+ *
+ * @param buf[in] A buffer handle obtained with #LSUP_buffer_new or by manual
+ *  allocation.
+ *
+ * @param size[in] New size.
+ *
+ * @param data[in] If not NULL, data to replace the existing ones. The size
+ * of the data to be copied is determined by the size parameter.
+ */
 LSUP_rc
-LSUP_buffer_new(size_t size, LSUP_Buffer *buf_p);
+LSUP_buffer_reset (LSUP_Buffer *buf, const size_t size, const void *data);
 
-LSUP_rc
-LSUP_buffer_reset(LSUP_Buffer *buf, size_t size);
 
-void LSUP_buffer_print(const LSUP_Buffer *buf);
+/** Initialize an allocated buffer handle.
+ *
+ * The handle must be freed with #LSUP_buffer_done after use.
+ *
+ * @param buf[in] A manually (stack or heap) allocated buffer handle.
+ *
+ * @param size[in] New size.
+ *
+ * @param data[in] If not NULL, data to replace the existing ones. The size
+ * of the data to be copied is determined by the size parameter.
+ */
+inline LSUP_rc
+LSUP_buffer_init (LSUP_Buffer *buf, const size_t size, const void *data)
+{
+    buf->addr = NULL;
+    return LSUP_buffer_reset(buf, size, data);
+}
+
+
+/** @brief Create a new buffer and optionally populate it with data.
+ *
+ * To change the buffer size later call #LSUP_buffer_reset.
+ *
+ * To copy a buffer just do buf2 = LSUP_buffer_new (buf1->size, buf1->addr);
+ *
+ * @param size[in] Length of the data.
+ *
+ * @param data[in] Optional data to initially populate the object with.
+ *
+ * @return LSUP_Buffer pointer. It must be freed with #LSUP_buffer_free. NULL
+ *  on error.
+ */
+inline LSUP_Buffer *
+LSUP_buffer_new (const size_t size, const void *data)
+{
+    LSUP_Buffer *buf;
+    CRITICAL (buf = malloc (sizeof (*buf)));
+
+    if (LSUP_buffer_init (buf, size, data) != LSUP_OK) {
+        free (buf);
+        return NULL;
+    }
+
+    return buf;
+}
 
-LSUP_rc
-LSUP_buffer_copy(const LSUP_Buffer *src, LSUP_Buffer *dest);
 
-void LSUP_buffer_free(LSUP_Buffer *buf);
+/** @brief Dummy buffer to be used with #LSUP_buffer_reset.
+ */
+#define BUF_DUMMY LSUP_buffer_new(0, NULL);
+
+
+/** @brief Free the content of a buffer.
+ */
+void LSUP_buffer_done(LSUP_Buffer *buf);
+
+
+/** @brief Free a buffer.
+ */
+void LSUP_buffer_free (LSUP_Buffer *buf);
+
+/** @brief Print a byte string of a given length in a human-readable format.
+ *
+ * The string is printed in Python style: printable characters are output
+ * literally, and non-printable ones as hex sequences.
+ */
+void LSUP_buffer_print (const LSUP_Buffer *buf);
 
 
 /** @brief Compare two buffers.
  *
  * The return value is the same as memcmp.
  */
-inline int LSUP_buffer_cmp(const LSUP_Buffer *buf1, const LSUP_Buffer *buf2)
-{ return memcmp(buf1->addr, buf2->addr, max(buf1->size, buf2->size)); }
+inline int LSUP_buffer_cmp (const LSUP_Buffer *buf1, const LSUP_Buffer *buf2)
+{ return memcmp (buf1->addr, buf2->addr, max (buf1->size, buf2->size)); }
 
 
 /** @brief Return whether two buffers are equal.
@@ -36,11 +121,11 @@ inline int LSUP_buffer_cmp(const LSUP_Buffer *buf1, const LSUP_Buffer *buf2)
  * This may be faster than #LSUP_buffer_cmp because it returns immediately if
  * the sizes of the buffers differ.
  */
-inline bool LSUP_buffer_eq(const LSUP_Buffer *buf1, const LSUP_Buffer *buf2)
+inline bool LSUP_buffer_eq (const LSUP_Buffer *buf1, const LSUP_Buffer *buf2)
 {
     if (buf1->size != buf2->size) return false;
 
-    return (LSUP_buffer_cmp(buf1, buf2) == 0) ? true : false;
+    return (LSUP_buffer_cmp (buf1, buf2) == 0) ? true : false;
 }
 
 #endif

+ 4 - 1
include/core.h

@@ -100,6 +100,9 @@ LSUP_rc mkdir_p(const char *path, mode_t mode);
 #define PCHECK(exp, rc, marker) (rc) = (exp); if ((rc) < LSUP_OK) goto marker
 
 // Return rc if it is of LSUP_rc type and is negative (=error)
-#define RCCK(exp) LSUP_rc _rc = (exp); if (_rc < 0) return _rc;
+#define RCCK(exp) LSUP_rc _rc = (exp); if (_rc < 0) return _rc
+
+// Return NULL if it is of LSUP_rc type and is negative (=error)
+#define RCNL(exp) if((exp) < 0) return NULL
 
 #endif

+ 8 - 40
include/graph.h

@@ -37,8 +37,8 @@ typedef struct GraphIterator LSUP_GraphIterator;
  *
  * @return LSUP_OK if the graph was created, or < 0 if an error occurred.
  */
-LSUP_rc
-LSUP_graph_new(const LSUP_store_type store_type, LSUP_Graph **gr);
+LSUP_Graph *
+LSUP_graph_new(const LSUP_store_type store_type);
 
 
 /** @brief copy a graph into a new one.
@@ -54,8 +54,8 @@ LSUP_graph_new(const LSUP_store_type store_type, LSUP_Graph **gr);
  *
  * @return LSUP_OK if the graph was copied, or < 0 if an error occurred.
  */
-LSUP_rc
-LSUP_graph_copy(const LSUP_Graph *src, LSUP_Graph **dest);
+LSUP_Graph *
+LSUP_graph_copy(const LSUP_Graph *src);
 
 
 /** Perform a boolean operation between two graphs.
@@ -71,10 +71,9 @@ LSUP_graph_copy(const LSUP_Graph *src, LSUP_Graph **dest);
  * @param res[out] Result graph. It must be freed with #LSUP_graph_free when
  *  done.
  */
-LSUP_rc
+LSUP_Graph *
 LSUP_graph_bool_op(
-        const LSUP_bool_op op, const LSUP_Graph *gr1, const LSUP_Graph *gr2,
-        LSUP_Graph **res);
+        const LSUP_bool_op op, const LSUP_Graph *gr1, const LSUP_Graph *gr2);
 
 
 /** @brief Free a graph.
@@ -176,10 +175,8 @@ LSUP_graph_remove(LSUP_Graph *gr, const LSUP_Triple *spo, size_t *ct);
  * @param it[out] Pointer to a #LSUP_GraphIterator to be generated. It must be
  *  freed with #LSUP_graph_iter_free after use.
  */
-LSUP_rc
-LSUP_graph_lookup(
-        const LSUP_Graph *gr, const LSUP_Triple *spo,
-        LSUP_GraphIterator **it_p);
+LSUP_GraphIterator *
+LSUP_graph_lookup(const LSUP_Graph *gr, const LSUP_Triple *spo);
 
 
 /** @brief Advance a cursor obtained by a lookup and return a matching triple.
@@ -200,33 +197,4 @@ LSUP_graph_iter_next(LSUP_GraphIterator *it, LSUP_Triple *spo);
 void
 LSUP_graph_iter_free(LSUP_GraphIterator *it);
 
-
-/**
- * Set-theoretical union (gr1 ∪ gr2).
- *
- * The resulting Keyset is initialized beforehand and is not compacted.
- */
-int LSUP_graph_join(LSUP_Graph *gr1, LSUP_Graph *gr2, LSUP_Graph *res);
-
-/**
- * Set-theoretical complement (gr1 \ gr2).
- *
- * The resulting Keyset is initialized beforehand and is not compacted.
- */
-int LSUP_graph_subtract(LSUP_Graph *gr1, LSUP_Graph *gr2, LSUP_Graph *res);
-
-/**
- * Set-theoretical intersection (gr1 ∩ gr2).
- *
- * The resulting Keyset is initialized beforehand and is not compacted.
- */
-int LSUP_graph_intersect(LSUP_Graph *gr1, LSUP_Graph *gr2, LSUP_Graph *res);
-
-/**
- * Disjunctive union (XOR) (gr1 ⊕ gr2).
- *
- * The resulting Keyset is initialized beforehand and is not compacted.
- */
-int LSUP_graph_xor(LSUP_Graph *gr1, LSUP_Graph *gr2, LSUP_Graph *res);
-
 #endif

+ 23 - 25
include/store_htable.h

@@ -27,8 +27,27 @@
 typedef struct HTStore LSUP_HTStore;
 typedef struct HTIterator LSUP_HTIterator;
 
-LSUP_rc
-LSUP_htstore_new(size_t capacity, LSUP_HTStore **ht_p);
+LSUP_HTStore *
+LSUP_htstore_new(size_t capacity);
+
+
+/** @brief Boolean operation on hash table triples.
+ *
+ * The resulting store is compacted to the minimum size necessary to hold all
+ * results.
+ *
+ * @param op[in] Operation type. See #LSUP_bool_op
+ *
+ * @param s1[in] First store.
+ *
+ * @param s2[in] Second store.
+ *
+ * @return New store resulting from the operation. It must be freed with
+ * #LSUP_htstore_free after use.
+ */
+LSUP_HTStore *
+LSUP_htstore_bool_op(
+        const LSUP_bool_op op, const LSUP_HTStore *s1, const LSUP_HTStore *s2);
 
 void
 LSUP_htstore_free(LSUP_HTStore *ht);
@@ -43,10 +62,9 @@ LSUP_rc
 LSUP_htstore_remove(
         LSUP_HTStore *store, const LSUP_SerTriple *sspo, size_t *ct);
 
-LSUP_rc
+LSUP_HTIterator *
 LSUP_htstore_lookup(
-        LSUP_HTStore *store, const LSUP_SerTriple *sspo,
-        LSUP_HTIterator **it_p, size_t *ct);
+        LSUP_HTStore *store, const LSUP_SerTriple *sspo, size_t *ct);
 
 htsize_t
 LSUP_htstore_size(LSUP_HTStore *ht);
@@ -60,24 +78,4 @@ LSUP_htiter_next(LSUP_HTIterator *it, LSUP_SerTriple *sspo);
 void
 LSUP_htiter_free(LSUP_HTIterator *it);
 
-
-/** @brief Boolean operation on hash table triples.
- *
- * The resulting store is compacted to the minimum size necessary to hold all
- * results.
- *
- * @param op[in] Operation type. See #LSUP_bool_op
- *
- * @param s1[in] First store.
- *
- * @param s2[in] Second store.
- *
- * @param dest[out] Destination store. It must be freed with #LSUP_htstore_free
- *  after use.
- */
-LSUP_rc
-LSUP_htstore_bool_op(
-        const LSUP_bool_op op, const LSUP_HTStore *s1, const LSUP_HTStore *s2,
-        LSUP_HTStore **dest);
-
 #endif  // _LSUP_STORE_HTABLE_H

+ 7 - 9
include/store_mdb.h

@@ -72,10 +72,8 @@ LSUP_rc LSUP_mdbstore_setup(char **path/*, bool clear*/);
  *  triples inserted without a context specified. If NULL, the store operates
  *  in triple mode.
  */
-LSUP_rc
-LSUP_mdbstore_new(
-        const char *path, const LSUP_Buffer *default_ctx,
-        LSUP_MDBStore **store);
+LSUP_MDBStore *
+LSUP_mdbstore_new(const char *path, const LSUP_Buffer *default_ctx);
 
 
 /** @brief Close a store and free its handle.
@@ -120,9 +118,8 @@ size_t LSUP_mdbstore_size(LSUP_MDBStore *store);
  * @param it[out] Pointer to an iterator pointer to be passed to the following
  *  load steps.
  */
-void
-LSUP_mdbstore_add_init(
-        LSUP_MDBStore *store, const LSUP_Buffer *sc, LSUP_MDBIterator **it);
+LSUP_MDBIterator *
+LSUP_mdbstore_add_init(LSUP_MDBStore *store, const LSUP_Buffer *sc);
 
 
 /** @brief Add one triple into the store.
@@ -213,9 +210,10 @@ LSUP_mdbstore_remove(
  *
  * @return LSUP_OK if entries were found, LSUP_NORESULT if none were found.
  */
-LSUP_rc LSUP_mdbstore_lookup(
+LSUP_MDBIterator *
+LSUP_mdbstore_lookup(
         LSUP_MDBStore *store, const LSUP_SerTriple *sspo,
-        const LSUP_Buffer *sc, LSUP_MDBIterator **it, size_t *ct);
+        const LSUP_Buffer *sc, size_t *ct);
 
 
 /** @brief Yield the matching triples and advance the iterator.

+ 54 - 16
include/term.h

@@ -22,6 +22,8 @@
 // triples in a keyset.
 #define NULL_TRP {NULL_KEY, NULL_KEY, NULL_KEY}
 
+#define UUID4_URN_SIZE UUIDSTR_SIZE + 10
+
 
 typedef XXH64_hash_t LSUP_TermHash64;
 typedef char langtag[LANG_SIZE];
@@ -60,10 +62,14 @@ typedef struct LSUP_Term {
  *
  * @return LSUP_OK if successful, LSUP_VALUE_ERR if validation fails.
  */
-LSUP_rc
+LSUP_Term *
 LSUP_term_new(
-        LSUP_term_type type, const char *data, char *datatype, char *lang,
-        LSUP_Term **term);
+        LSUP_term_type type, const char *data, char *datatype, char *lang);
+
+
+/** @brief Placeholder term to use with LSUP_term_reset.
+ */
+#define TERM_DUMMY LSUP_term_new(LSUP_TERM_UNDEFINED, NULL, NULL, NULL)
 
 
 /** @brief Shortcut to create a URI.
@@ -76,8 +82,8 @@ LSUP_term_new(
  *
  * @return LSUP_OK if successful, LSUP_VALUE_ERR if validation fails.
  */
-inline LSUP_rc
-LSUP_uri_new(const char *data, LSUP_Term **uri)
+inline LSUP_Term *
+LSUP_uri_new(const char *data)
 {
     if (!data) {
         uuid_t uuid;
@@ -86,13 +92,13 @@ LSUP_uri_new(const char *data, LSUP_Term **uri)
         uuid_str_t uuid_str;
         uuid_unparse_lower(uuid, uuid_str);
 
-        char uri[UUIDSTR_SIZE + 10];
-        sprintf(uri, "urn:uuid4:%s", uuid_str);
+        char uri[UUID4_URN_SIZE];
+        snprintf(uri, UUID4_URN_SIZE, "urn:uuid4:%s", uuid_str);
 
         data = uri;
     }
 
-    return LSUP_term_new(LSUP_TERM_URI, data, NULL, NULL, uri);
+    return LSUP_term_new(LSUP_TERM_URI, data, NULL, NULL);
 }
 
 
@@ -103,26 +109,57 @@ LSUP_uri_new(const char *data, LSUP_Term **uri)
  * freed with #LSUP_term_free.
  */
 LSUP_rc
-LSUP_term_reset(
+LSUP_term_init(
         LSUP_Term *term, LSUP_term_type type,
         const char *data, char *datatype, char *lang);
 
 
+LSUP_Term *
+LSUP_term_new_from_buffer(const LSUP_Buffer *sterm);
+
+
+LSUP_Buffer *
+LSUP_buffer_new_from_term(const LSUP_Term *term);
+
+
 /**
  * @brief Shortcut to initialize a URI.
  */
 inline LSUP_rc
-LSUP_uri_reset(LSUP_Term *term, const char *data)
-{ return LSUP_term_reset(term, LSUP_TERM_URI, data, NULL, NULL); }
+LSUP_uri_init(LSUP_Term *term, const char *data)
+{
+    if (!data) {
+        uuid_t uuid;
+        uuid_generate_random(uuid);
+
+        uuid_str_t uuid_str;
+        uuid_unparse_lower(uuid, uuid_str);
+
+        char uri[UUIDSTR_SIZE + 10];
+        sprintf(uri, "urn:uuid4:%s", uuid_str);
+
+        data = uri;
+    }
+
+    return LSUP_term_init(term, LSUP_TERM_URI, data, NULL, NULL);
+}
 
 
 /** @brief Simple ad-hoc serialization function.
  *
  * The resulting term must be freed with #LSUP_term_free after use.
  */
-LSUP_rc LSUP_term_serialize(const LSUP_Term *term, LSUP_Buffer **sterm);
+LSUP_rc
+LSUP_term_serialize(const LSUP_Term *term, LSUP_Buffer *sterm);
+
 
-LSUP_rc LSUP_term_deserialize(const LSUP_Buffer *sterm, LSUP_Term **term);
+/** @brief Deserialize a buffer into a term.
+ *
+ * The buffer must be a well-formed serialization of a term, e.g. as obtained
+ * by #LSUP_term_serialize.
+ */
+LSUP_rc
+LSUP_term_deserialize(const LSUP_Buffer *sterm, LSUP_Term *term);
 
 
 inline LSUP_Key
@@ -143,9 +180,7 @@ LSUP_term_to_key(const LSUP_Term *term)
 {
     if (UNLIKELY (term == NULL)) return NULL_KEY;
 
-    LSUP_Buffer *sterm;
-
-    LSUP_term_serialize(term, &sterm);
+    LSUP_Buffer *sterm = LSUP_buffer_new_from_term(term);
     LSUP_Key key = XXH64(sterm->addr, sterm->size, SEED);
 
     LSUP_buffer_free(sterm);
@@ -164,6 +199,9 @@ inline XXH128_hash_t
 LSUP_term_hash128(const LSUP_Term *term);
 */
 
+void
+LSUP_term_done(LSUP_Term *term);
+
 void
 LSUP_term_free(LSUP_Term *term);
 

+ 0 - 8
include/triple.h

@@ -51,9 +51,6 @@ LSUP_triple_deserialize(const LSUP_SerTriple *sspo, LSUP_Triple *spo);
 
 
 /** @brief Free the internal pointers of a triple.
- *
- * The striple structure itself is not freed, so it can be used with a stack-
- * allocated structure.
  *
  * @param spo[in] Triple to be freed.
  */
@@ -62,9 +59,6 @@ LSUP_triple_done(LSUP_Triple *spo);
 
 
 /** @brief Free the internal pointers of a buffer triple.
- *
- * The triple structure itself is not freed, so it can be used with a stack-
- * allocated structure.
  *
  * @param sspo[in] Buffer triple to be freed.
  */
@@ -110,6 +104,4 @@ LSUP_striple_pos(const LSUP_SerTriple *trp, LSUP_TriplePos n)
 
 #undef _FN_BODY
 
-
-// TODO Add constructors and destructors with term type checks.
 #endif

+ 23 - 41
src/buffer.c

@@ -1,71 +1,53 @@
 #include "buffer.h"
 
-// Inline extern prototypes
+/* * * Inline extern prototypes * * */
 
-bool LSUP_buffer_eq(const LSUP_Buffer *buf1, const LSUP_Buffer *buf2);
-int LSUP_buffer_cmp(const LSUP_Buffer *buf1, const LSUP_Buffer *buf2);
+LSUP_Buffer *LSUP_buffer_new (const size_t size, const void *data);
+LSUP_rc LSUP_buffer_init (
+        LSUP_Buffer *buf, const size_t size, const void *data);
+bool LSUP_buffer_eq (const LSUP_Buffer *buf1, const LSUP_Buffer *buf2);
+int LSUP_buffer_cmp (const LSUP_Buffer *buf1, const LSUP_Buffer *buf2);
 
 
+/* * * API * * */
+
 LSUP_rc
-LSUP_buffer_new(size_t size, LSUP_Buffer *buf)
+LSUP_buffer_reset (LSUP_Buffer *buf, const size_t size, const void *data)
 {
-    LSUP_Buffer *tmp;
-    CRITICAL(tmp = malloc (sizeof (*tmp)));
-    buf->addr = NULL; // TODO redundant?
+    void *tmp = realloc (buf->addr, size);
+    if (UNLIKELY (!tmp)) return LSUP_ERROR;
 
-    RCCK (LSUP_buffer_reset(buf, size));
+    buf->addr = tmp;
+    buf->size = size;
 
-    *buf = *tmp;
+    if (data) memcpy (buf->addr, data, buf->size);
 
     return LSUP_OK;
 }
 
 
-LSUP_rc
-LSUP_buffer_reset(LSUP_Buffer *buf, size_t size)
+void LSUP_buffer_print (const LSUP_Buffer *buf)
 {
-    //TRACE("Buffer Size: %lu\n", size);
-    CRITICAL (buf->addr = realloc (buf->addr, size));
-    buf->size = size;
-
-    return LSUP_OK;
-}
-
-/**
- * Print a byte string of a given length in a human-readable format.
- *
- * The string is printed in Python style: printable characters are output
- * literally, and non-printable ones as hex sequences.
- */
-void LSUP_buffer_print(const LSUP_Buffer *buf) {
     for (size_t i = 0; i < buf->size; i++) {
         char chr = ((char*)buf->addr)[i];
-        if (isprint(chr)) {
-            fputc(chr, stdout);
+        if (isprint (chr)) {
+            fputc (chr, stdout);
         } else {
-            printf("\\x%02x", chr);
+            printf ("\\x%02x", chr);
         }
     }
     printf("\n");
 }
 
 
-LSUP_rc
-LSUP_buffer_copy(const LSUP_Buffer *src, LSUP_Buffer *dest)
+void LSUP_buffer_done(LSUP_Buffer *buf)
 {
-    LSUP_Buffer *tmp;
-    RCCK (LSUP_buffer_reset(tmp, src->size));
-
-    memcpy(tmp->addr, src->addr, src->size);
-
-    *dest = *tmp;
-
-    return LSUP_OK;
+    if (LIKELY (buf)) free(buf->addr);
 }
 
-
-void LSUP_buffer_free(LSUP_Buffer *buf){
-    if (LIKELY (buf)) free(buf->addr);
+void LSUP_buffer_free (LSUP_Buffer *buf)
+{
+    LSUP_buffer_done (buf);
     free(buf);
 }
 

+ 58 - 95
src/graph.c

@@ -70,7 +70,7 @@ graph_iter_next_buffer(GraphIterator *it, LSUP_SerTriple *sspo);
 
 
 /* Atexit functions. */
-void ctx_cleanup() { free(default_ctx); }
+void ctx_cleanup() { LSUP_buffer_done(default_ctx); }
 
 
 static inline bool is_null_trp(const LSUP_TripleKey *trp)
@@ -84,33 +84,30 @@ static inline bool is_null_trp(const LSUP_TripleKey *trp)
 
 /* * * GRAPH * * */
 
-LSUP_rc
-LSUP_graph_new(const LSUP_store_type store_type, Graph **gr_p)
+Graph *
+LSUP_graph_new(const LSUP_store_type store_type)
 {
     LSUP_Graph *gr;
     CRITICAL(gr = malloc(sizeof(LSUP_Graph)));
 
-    *gr_p = gr;
-
     // Initialize default context only once per process.
     if(UNLIKELY(!default_ctx)) {
-        LSUP_Term default_ctx_uri;
-        LSUP_uri_new(default_ctx_label, &default_ctx_uri);
-        LSUP_term_serialize(&default_ctx_uri, default_ctx);
-        LSUP_term_free(&default_ctx_uri);
+        LSUP_Term *default_ctx_uri = LSUP_uri_new(default_ctx_label);
+        LSUP_term_serialize(default_ctx_uri, default_ctx);
+        LSUP_term_free(default_ctx_uri);
         atexit(ctx_cleanup);
     }
 
     if (store_type == LSUP_STORE_MEM) {
-        LSUP_htstore_new(0, &gr->ht_store);
+        gr->ht_store = LSUP_htstore_new(0);
 
     } else if (store_type == LSUP_STORE_MDB) {
-        LSUP_mdbstore_new(
-                getenv("LSUP_MDB_STORE_PATH"), default_ctx, &gr->mdb_store);
+        gr->mdb_store = LSUP_mdbstore_new(
+                getenv("LSUP_MDB_STORE_PATH"), default_ctx);
 
-    } else return LSUP_VALUE_ERR;
+    } else return NULL;
 
-    return LSUP_OK;
+    return gr;
 }
 
 
@@ -124,9 +121,8 @@ graph_copy_contents(const LSUP_Graph *src, LSUP_Graph *dest)
 {
     LSUP_rc rc = LSUP_NOACTION;
     const LSUP_Triple trp = {NULL, NULL, NULL};
-    GraphIterator *it;
 
-    LSUP_graph_lookup(src, &trp, &it);
+    GraphIterator *it = LSUP_graph_lookup(src, &trp);
 
     LSUP_SerTriple sspo;
 
@@ -141,27 +137,22 @@ graph_copy_contents(const LSUP_Graph *src, LSUP_Graph *dest)
 }
 
 
-LSUP_rc
-LSUP_graph_copy(const Graph *src, Graph **dest_p)
+LSUP_Graph *
+LSUP_graph_copy(const Graph *src)
 {
-    LSUP_rc rc;
-    LSUP_Graph *dest;
-
-    rc = LSUP_graph_new(src->store_type, &dest);
-    if (UNLIKELY (rc != LSUP_OK)) return rc;
-
-    rc = graph_copy_contents(src, dest);
+    LSUP_Graph *dest = LSUP_graph_new(src->store_type);
+    if (UNLIKELY (!dest)) return NULL;
 
-    if (LIKELY (rc == LSUP_OK)) *dest_p = dest;
+    LSUP_rc rc = graph_copy_contents(src, dest);
+    if (UNLIKELY (rc != LSUP_OK)) return NULL;
 
-    return rc;
+    return dest;
 }
 
 
-LSUP_rc
+Graph *
 LSUP_graph_bool_op(
-        const LSUP_bool_op op, const Graph *gr1, const Graph *gr2,
-        Graph **res_p)
+        const LSUP_bool_op op, const Graph *gr1, const Graph *gr2)
 {
     if (UNLIKELY (gr1->store_type != LSUP_STORE_MEM)) {
         fprintf(
@@ -169,7 +160,7 @@ LSUP_graph_bool_op(
                 "First operand %s is not an in-memory graph. "
                 "Cannot perform boolean operation.",
                 gr1->uri->data);
-        return LSUP_VALUE_ERR;
+        return NULL;
     }
     if (UNLIKELY (gr2->store_type != LSUP_STORE_MEM)) {
         fprintf(
@@ -177,14 +168,13 @@ LSUP_graph_bool_op(
                 "Second operand %s is not an in-memory graph. "
                 "Cannot perform boolean operation.",
                 gr2->uri->data);
-        return LSUP_VALUE_ERR;
+        return NULL;
     }
 
-    LSUP_Graph *res;
-    LSUP_graph_new(LSUP_STORE_MEM, &res);
+    LSUP_Graph *res = LSUP_graph_new(LSUP_STORE_MEM);
+    res->ht_store = LSUP_htstore_bool_op(op, gr1->ht_store, gr2->ht_store);
 
-    return LSUP_htstore_bool_op(
-            op, gr1->ht_store, gr2->ht_store, &res->ht_store);
+    return res;
 }
 
 
@@ -210,7 +200,7 @@ LSUP_graph_uri(const LSUP_Graph *gr) { return gr->uri; }
 
 LSUP_rc
 LSUP_graph_set_uri(LSUP_Graph *gr, const char *uri)
-{ return LSUP_uri_new(uri, gr->uri); }
+{ return LSUP_uri_init(gr->uri, uri); }
 
 
 LSUP_rc
@@ -270,13 +260,9 @@ LSUP_graph_add(
 
         // Serialize and insert RDF triples.
         if (trp_ct > 0) {
-            LSUP_SerTriple sspo;
-
             for (size_t i = 0; i < trp_ct; i++) {
-
-                LSUP_term_serialize(trp[i].s, sspo.s);
-                LSUP_term_serialize(trp[i].p, sspo.p);
-                LSUP_term_serialize(trp[i].o, sspo.o);
+                LSUP_SerTriple sspo;
+                LSUP_triple_serialize(trp + i, &sspo);
 
                 TRACE("Inserting triple #%lu\n", i);
                 LSUP_rc db_rc = LSUP_htstore_add(gr->ht_store, &sspo);
@@ -284,12 +270,11 @@ LSUP_graph_add(
                     rc = LSUP_OK;
                     (*inserted) ++;
                 }
+
+                LSUP_striple_done(&sspo);
+
                 if (UNLIKELY (db_rc < 0)) return db_rc;
             }
-
-            LSUP_buffer_done(sspo.s);
-            LSUP_buffer_done(sspo.p);
-            LSUP_buffer_done(sspo.o);
         }
 
         // Insert serialized triples.
@@ -313,18 +298,14 @@ LSUP_graph_add(
         LSUP_Buffer sc;
         LSUP_term_serialize(gr->uri, &sc);
 
-        LSUP_MDBIterator *it;
-        LSUP_mdbstore_add_init(gr->mdb_store, &sc, &it);
+        LSUP_MDBIterator *it = LSUP_mdbstore_add_init(gr->mdb_store, &sc);
+        LSUP_buffer_done(&sc);
 
         // Serialize and insert RDF triples.
         if (trp_ct > 0) {
-            LSUP_SerTriple sspo;
-
             for (size_t i = 0; i < trp_ct; i++) {
-
-                LSUP_term_serialize(trp[i].s, sspo.s);
-                LSUP_term_serialize(trp[i].p, sspo.p);
-                LSUP_term_serialize(trp[i].o, sspo.o);
+                LSUP_SerTriple sspo;
+                LSUP_triple_serialize(trp + i, &sspo);
 
                 TRACE("Inserting triple #%lu\n", i);
                 LSUP_rc db_rc = LSUP_mdbstore_add_iter(it, &sspo);
@@ -333,12 +314,11 @@ LSUP_graph_add(
                     rc = LSUP_OK;
                     (*inserted) ++;
                 }
-                if (UNLIKELY(db_rc < 0)) return db_rc;
-            }
 
-            LSUP_buffer_done(sspo.s);
-            LSUP_buffer_done(sspo.p);
-            LSUP_buffer_done(sspo.o);
+                LSUP_striple_done(&sspo);
+
+                if (UNLIKELY (db_rc < 0)) return db_rc;
+            }
         }
 
         // Insert serialized triples.
@@ -364,61 +344,46 @@ LSUP_rc
 LSUP_graph_remove(Graph *gr, const LSUP_Triple *spo, size_t *ct)
 {
     LSUP_rc rc;
-    LSUP_SerTriple sspo_s;
-    LSUP_SerTriple *sspo = &sspo_s;
-    LSUP_Buffer sc_s;
-    LSUP_Buffer *sc = &sc_s;
 
-    LSUP_term_serialize(spo->s, sspo->s);
-    LSUP_term_serialize(spo->p, sspo->s);
-    LSUP_term_serialize(spo->o, sspo->s);
-    LSUP_term_serialize(gr->uri, sc);
+    LSUP_SerTriple sspo;
+    LSUP_triple_serialize(spo, &sspo);
+    LSUP_Buffer *sc = LSUP_buffer_new_from_term(gr->uri);
 
     if (gr->store_type == LSUP_STORE_MEM)
-        rc = LSUP_htstore_remove(gr->ht_store, sspo, ct);
+        rc = LSUP_htstore_remove(gr->ht_store, &sspo, ct);
     else
-        rc = LSUP_mdbstore_remove(gr->mdb_store, sspo, sc, ct);
+        rc = LSUP_mdbstore_remove(gr->mdb_store, &sspo, sc, ct);
 
-    LSUP_striple_done(sspo);
-    LSUP_buffer_done(sc);
+    LSUP_striple_done(&sspo);
+    LSUP_buffer_free(sc);
 
     return rc;
 }
 
 
-LSUP_rc
-LSUP_graph_lookup(
-        const Graph *gr, const LSUP_Triple *spo, GraphIterator **it_p)
+GraphIterator *
+LSUP_graph_lookup(const Graph *gr, const LSUP_Triple *spo)
 {
-    LSUP_rc rc;
     GraphIterator *it;
     CRITICAL(it = malloc(sizeof(GraphIterator)));
-    *it_p = it;
 
     it->graph = gr;
 
-    LSUP_SerTriple sspo_s;
-    LSUP_SerTriple *sspo = &sspo_s;
-    LSUP_Buffer sc_s;
-    LSUP_Buffer *sc = &sc_s;
-
-    LSUP_term_serialize(spo->s, sspo->s);
-    LSUP_term_serialize(spo->p, sspo->s);
-    LSUP_term_serialize(spo->o, sspo->s);
-    LSUP_term_serialize(gr->uri, sc);
+    LSUP_SerTriple sspo;
+    LSUP_triple_serialize(spo, &sspo);
+    LSUP_Buffer *sc = LSUP_buffer_new_from_term(gr->uri);
 
     if (gr->store_type == LSUP_STORE_MEM) {
-        rc = LSUP_htstore_lookup(gr->ht_store, sspo, &it->ht_iter, &it->ct);
+        it->ht_iter = LSUP_htstore_lookup(gr->ht_store, &sspo, &it->ct);
 
     } else {
-        rc = LSUP_mdbstore_lookup(
-                gr->mdb_store, sspo, sc, &it->mdb_iter, &it->ct);
+        it->mdb_iter = LSUP_mdbstore_lookup(gr->mdb_store, &sspo, sc, &it->ct);
     }
 
-    LSUP_striple_done(sspo);
-    LSUP_buffer_done(sc);
+    LSUP_striple_done(&sspo);
+    LSUP_buffer_free(sc);
 
-    return rc;
+    return it;
 }
 
 
@@ -473,9 +438,7 @@ LSUP_graph_iter_free(GraphIterator *it)
 bool
 LSUP_graph_contains(const LSUP_Graph *gr, const LSUP_Triple *spo)
 {
-    GraphIterator *it;
-
-    LSUP_graph_lookup(gr, spo, &it);
+    GraphIterator *it = LSUP_graph_lookup(gr, spo);
     bool rc = LSUP_graph_iter_next(it, NULL) != LSUP_NORESULT;
 
     LSUP_graph_iter_free(it);

+ 37 - 39
src/store_htable.c

@@ -109,22 +109,20 @@ static inline LSUP_rc htiter_next_key(HTIterator *it);
 
 /* * * API * * */
 
-LSUP_rc
-LSUP_htstore_new(size_t capacity, HTStore **ht_p)
+HTStore *
+LSUP_htstore_new(size_t capacity)
 {
     HTStore *ht;
-    CRITICAL(ht = malloc(sizeof(HTStore)));
-    *ht_p = ht;
+    CRITICAL(ht = malloc (sizeof (*ht)));
 
-    LSUP_rc rc = LSUP_htable_new(
-            capacity, TRP_KLEN, 0, xx64_hash_fn, buffer_eq_fn, &ht->keys);
-    if (rc != LSUP_OK) return rc;
+    ht->keys = LSUP_htable_new(
+            capacity, TRP_KLEN, 0, xx64_hash_fn, buffer_eq_fn);
 
-    rc = LSUP_htable_new(
+    ht->idx = LSUP_htable_new(
         capacity * IDX_SIZE_RATIO, sizeof(uint64_t), sizeof(uintptr_t),
-        xx64_hash_fn, buffer_eq_fn, &ht->idx);
+        xx64_hash_fn, buffer_eq_fn);
 
-    return rc;
+    return ht;
 }
 
 void
@@ -195,13 +193,12 @@ LSUP_rc
 LSUP_htstore_remove(
         LSUP_HTStore *store, const LSUP_SerTriple *sspo, size_t *ct)
 {
-    LSUP_HTIterator *it;
-    LSUP_rc rc = LSUP_htstore_lookup(store, sspo, &it, ct);
-    if (UNLIKELY (rc != LSUP_OK)) return rc;
+    LSUP_HTIterator *it = LSUP_htstore_lookup(store, sspo, ct);
+    if (UNLIKELY (!it)) return LSUP_DB_ERR;
 
     *ct = 0;
     while (htiter_next_key (it)) {
-        rc = LSUP_htable_remove(store->keys, it->spok);
+        LSUP_rc rc = LSUP_htable_remove(store->keys, it->spok);
         if (UNLIKELY (rc < 0)) return rc;
 
         (*ct) ++;
@@ -212,13 +209,16 @@ LSUP_htstore_remove(
 }
 
 
-LSUP_rc
-LSUP_htstore_lookup(
-        HTStore *store, const LSUP_SerTriple *sspo,
-        HTIterator **it_p, size_t *ct)
+HTIterator *
+LSUP_htstore_lookup(HTStore *store, const LSUP_SerTriple *sspo, size_t *ct)
 {
-    if (LSUP_htable_size(store->keys) == 0)
-        return LSUP_NOACTION;
+    HTIterator *it;
+    CRITICAL(it = malloc (sizeof (*it)));
+    it->store = store;
+    it->cur = 0;
+    it->rc = LSUP_END;
+
+    if (LSUP_htable_size(store->keys) == 0) return it;
 
     LSUP_TripleKey spok = {
         LSUP_sterm_to_key(sspo->s),
@@ -226,12 +226,6 @@ LSUP_htstore_lookup(
         LSUP_sterm_to_key(sspo->o),
     };
 
-    HTIterator *it;
-    CRITICAL(it = malloc(sizeof(HTIterator)));
-    it->store = store;
-    it->cur = 0;
-    *it_p = it;
-
     // s p o
     if (spok[0] != NULL_KEY && spok[1] != NULL_KEY && spok[2] != NULL_KEY) {
         memcpy(it->luk, spok, sizeof(LSUP_TripleKey));
@@ -277,7 +271,7 @@ LSUP_htstore_lookup(
     it->rc = LSUP_htable_iter(
             it->store->keys, &it->cur, (void**)&it->spok, NULL);
 
-    return it->rc >= 0 ? LSUP_OK : it->rc;
+    return it->rc >= 0 ? it : NULL;
 }
 
 
@@ -314,30 +308,31 @@ LSUP_htiter_free(LSUP_HTIterator *it)
 { free(it); }
 
 
-LSUP_rc
+HTStore *
 LSUP_htstore_bool_op(
-        const LSUP_bool_op op, const HTStore *s1, const HTStore *s2,
-        HTStore **dest_p)
+        const LSUP_bool_op op, const HTStore *s1, const HTStore *s2)
 {
     HTStore *dest;
     htsize_t cur;
     void *key, *val;
 
-    LSUP_htstore_new(0, &dest);
-    *dest_p = dest;
+    dest = LSUP_htstore_new(0);
 
     if (UNLIKELY (
             op != LSUP_BOOL_UNION
             && op != LSUP_BOOL_SUBTRACTION
             && op != LSUP_BOOL_INTERSECTION
-            && op != LSUP_BOOL_XOR)) return LSUP_VALUE_ERR;
+            && op != LSUP_BOOL_XOR)) {
+        fprintf(stderr, "Operation not supported.\n");
+        goto fail;
+    }
 
     if (op == LSUP_BOOL_UNION) {
-        LSUP_htable_copy(s1->keys, &dest->keys);
+        dest->keys = LSUP_htable_copy(s1->keys);
         while (LSUP_htable_iter(s2->keys, &cur, &key, NULL) != LSUP_END)
             LSUP_htable_put(dest->keys, key, NULL);
 
-        LSUP_htable_copy(s1->idx, &dest->idx);
+        dest->idx = LSUP_htable_copy(s1->idx);
         while (LSUP_htable_iter(s2->idx, &cur, &key, &val) != LSUP_END)
             LSUP_htable_put(dest->idx, key, val);
 
@@ -351,9 +346,8 @@ LSUP_htstore_bool_op(
                     if (LSUP_htable_get(s2->idx, key, &val) == LSUP_OK)
                         LSUP_htable_put(dest->idx, key, val);
 
-                } else if (UNLIKELY(get_rc < 0)) return get_rc;
+                } else if (UNLIKELY(get_rc < 0)) goto fail;
             }
-
         }
 
         while (LSUP_htable_iter(s1->keys, &cur, &key, NULL) != LSUP_END) {
@@ -367,9 +361,13 @@ LSUP_htstore_bool_op(
                 if (LSUP_htable_get(s1->idx, key, &val) == LSUP_OK)
                     LSUP_htable_put(dest->idx, key, val);
 
-            } else if (UNLIKELY(get_rc < 0)) return get_rc;
+            } else if (UNLIKELY(get_rc < 0)) goto fail;
         }
     }
 
-    return LSUP_OK;
+    return dest;
+
+fail:
+    LSUP_htstore_free(dest);
+    return NULL;
 }

+ 34 - 41
src/store_mdb.c

@@ -277,24 +277,19 @@ LSUP_mdbstore_setup(char **path/*, bool clear*/) // TODO clear
 }
 
 
-LSUP_rc
-LSUP_mdbstore_new(
-        const char *path, const LSUP_Buffer *default_ctx,
-        LSUP_MDBStore **store_p)
+MDBStore *
+LSUP_mdbstore_new(const char *path, const LSUP_Buffer *default_ctx)
 {
     int rc;
     LSUP_MDBStore *store;
     CRITICAL(store = malloc(sizeof(LSUP_MDBStore)));
-    *store_p = NULL;
 
     rc = mdb_env_create(&store->env);
     TRACE("create rc: %d", rc);
 
-    if (default_ctx == NULL) store->default_ctx = NULL;
-    else {
-        CRITICAL(store->default_ctx = malloc(sizeof(LSUP_Buffer)));
-        LSUP_buffer_copy(default_ctx, &store->default_ctx);
-    }
+    store->default_ctx = (
+            default_ctx ?
+            LSUP_buffer_new(default_ctx->size, default_ctx->addr) : NULL);
 
     // Set map size.
     size_t mapsize;
@@ -303,20 +298,19 @@ LSUP_mdbstore_new(
     else sscanf(env_mapsize, "%lu", &mapsize);
 
     rc = mdb_env_set_maxdbs(store->env, N_DB);
-    if(rc != MDB_SUCCESS) return LSUP_DB_ERR;
+    if (UNLIKELY (rc != MDB_SUCCESS)) return NULL;
 
     rc = mdb_env_open(store->env, path, 0, ENV_FILE_MODE);
-    if (rc != MDB_SUCCESS) return LSUP_DB_ERR;
+    if (UNLIKELY (rc != MDB_SUCCESS)) return NULL;
 
     // Assign DB handles to store->dbi.
     MDB_txn *txn;
     mdb_txn_begin(store->env, NULL, 0, &txn);
     for (int i = 0; i < N_DB; i++) {
-        rc = mdb_dbi_open(
-                txn, db_labels[i], db_flags[i], store->dbi + i);
-        if (rc != MDB_SUCCESS) {
+        rc = mdb_dbi_open(txn, db_labels[i], db_flags[i], store->dbi + i);
+        if (UNLIKELY (rc != MDB_SUCCESS)) {
             mdb_txn_abort(txn);
-            return LSUP_DB_ERR;
+            return NULL;
         }
     }
 
@@ -325,9 +319,7 @@ LSUP_mdbstore_new(
     store->state |= LSSTORE_OPEN;
     store->txn = NULL;
 
-    *store_p = store;
-
-    return LSUP_OK;
+    return store;
 }
 
 
@@ -382,15 +374,14 @@ LSUP_mdbstore_size(LSUP_MDBStore *store)
 }
 
 
-void
-LSUP_mdbstore_add_init(
-        LSUP_MDBStore *store, const LSUP_Buffer *sc, MDBIterator **it_p)
+MDBIterator *
+LSUP_mdbstore_add_init(LSUP_MDBStore *store, const LSUP_Buffer *sc)
 {
     /* An iterator is used here. Some members are a bit misused but it does
      * its job without having to define a very similar struct.
      */
     MDBIterator *it;
-    CRITICAL(it= malloc(sizeof(MDBIterator)));
+    CRITICAL (it = malloc (sizeof (*it)));
     it->i = 0;
 
     if (!store->txn) {
@@ -421,7 +412,7 @@ LSUP_mdbstore_add_init(
             it->rc = LSUP_DB_ERR;
     }
 
-    *it_p = it;
+    return it;
 }
 
 
@@ -508,8 +499,7 @@ LSUP_mdbstore_add(
         LSUP_MDBStore *store, const LSUP_Buffer *sc,
         const LSUP_SerTriple strp[], const size_t ct, size_t *inserted)
 {
-    MDBIterator *it;
-    LSUP_mdbstore_add_init(store, sc, &it);
+    MDBIterator *it = LSUP_mdbstore_add_init(store, sc);
     if (it->rc < 0) {
         for (size_t i = 0; i < ct; i++)
             if (LSUP_mdbstore_add_iter(it, strp + i) < 0) break;
@@ -557,10 +547,10 @@ LSUP_mdbstore_key_to_sterm(
 }
 
 
-LSUP_rc
+MDBIterator *
 LSUP_mdbstore_lookup(
         LSUP_MDBStore *store, const LSUP_SerTriple *sspo,
-        const LSUP_Buffer *sc, MDBIterator **it_p, size_t *ct)
+        const LSUP_Buffer *sc, size_t *ct)
 {
     LSUP_TripleKey spok = {
         LSUP_sterm_to_key(sspo->s),
@@ -569,8 +559,7 @@ LSUP_mdbstore_lookup(
     };
 
     LSUP_MDBIterator *it;
-    CRITICAL(it = malloc(sizeof(MDBIterator)));
-    *it_p = it;
+    CRITICAL(it = malloc (sizeof (*it)));
 
     it->store = store;
     it->ck = store->default_ctx ? LSUP_sterm_to_key(sc) : NULL_KEY;
@@ -584,7 +573,7 @@ LSUP_mdbstore_lookup(
         it->luk[0] = spok[0];
         it->luk[1] = spok[1];
         it->luk[2] = spok[2];
-        return lookup_3bound(store, it, ct);
+        RCNL (lookup_3bound (store, it, ct));
 
     } else if (spok[0] != NULL_KEY) {
         it->luk[0] = spok[0];
@@ -594,16 +583,16 @@ LSUP_mdbstore_lookup(
         if (spok[1] != NULL_KEY) {
             it->luk[1] = spok[1];
             idx1 = 1;
-            return lookup_2bound(store, idx0, idx1, it, ct);
+            RCNL (lookup_2bound (store, idx0, idx1, it, ct));
 
         // s ? o
         } else if (spok[2] != NULL_KEY) {
             it->luk[1] = spok[2];
             idx1 = 2;
-            return lookup_2bound(store, idx0, idx1, it, ct);
+            RCNL (lookup_2bound (store, idx0, idx1, it, ct));
 
         // s ? ?
-        } else return lookup_1bound(store, idx0, it, ct);
+        } else RCNL (lookup_1bound (store, idx0, it, ct));
 
     } else if (spok[1] != NULL_KEY) {
         it->luk[0] = spok[1];
@@ -613,29 +602,33 @@ LSUP_mdbstore_lookup(
         if (spok[2] != NULL_KEY) {
             it->luk[1] = spok[2];
             idx1 = 2;
-            return lookup_2bound(store, idx0, idx1, it, ct);
+            RCNL (lookup_2bound (store, idx0, idx1, it, ct));
 
         // ? p ?
-        } else return lookup_1bound(store, idx0, it, ct);
+        } else RCNL (lookup_1bound (store, idx0, it, ct));
 
     // ? ? o
     } else if (spok[2] != NULL_KEY) {
         it->luk[0] = spok[2];
         idx0 = 2;
-        return lookup_1bound(store, idx0, it, ct);
+        RCNL (lookup_1bound(store, idx0, it, ct));
 
     // ? ? ? (all terms unbound)
-    } else return lookup_0bound(store, it, ct);
+    } else RCNL (lookup_0bound(store, it, ct));
+
+    return it;
 }
 
 
 LSUP_rc
 mdbiter_next_key(LSUP_MDBIterator *it)
 {
+    if (UNLIKELY (!it)) return LSUP_DB_ERR;
+
     // Only advance if the previous it->rc wasn't already at the end.
     if(it->rc == MDB_NOTFOUND) return LSUP_END;
 
-    if(it->rc != MDB_SUCCESS) {
+    if (UNLIKELY (it->rc != MDB_SUCCESS)) {
         fprintf(stderr, mdb_strerror(it->rc));
         return LSUP_DB_ERR;
     }
@@ -750,8 +743,8 @@ LSUP_mdbstore_remove(
     spok_v.mv_size = TRP_KLEN;
     ck_v.mv_size = KLEN;
 
-    LSUP_MDBIterator *it;
-    LSUP_mdbstore_lookup(store, sspo, sc, &it, ct);
+    LSUP_MDBIterator *it = LSUP_mdbstore_lookup(store, sspo, sc, ct);
+    if (UNLIKELY (!it)) return LSUP_DB_ERR;
 
     while (mdbiter_next_key(it)) {
         spok_v.mv_data = it->spok;

+ 53 - 27
src/term.c

@@ -8,8 +8,9 @@ static bool ptn_init = false;
 
 /* Global inline prototypes. */
 
-LSUP_rc LSUP_uri_reset(LSUP_Term *term, const char *data);
-LSUP_rc LSUP_uri_new(const char *data, LSUP_Term **term);
+LSUP_Term *LSUP_uri_new (const char *data);
+LSUP_rc LSUP_uri_init(LSUP_Term *term, const char *data);
+LSUP_rc LSUP_uri_reset (LSUP_Term *term, const char *data);
 
 
 /**
@@ -18,24 +19,58 @@ LSUP_rc LSUP_uri_new(const char *data, LSUP_Term **term);
 void term_cleanup() { if (ptn_init) regfree(&ptn); }
 
 
-LSUP_rc
-LSUP_term_new(
-        LSUP_term_type type, const char *data, char *datatype, char *lang,
-        LSUP_Term **term_p) {
+LSUP_Term *
+LSUP_term_new (
+        LSUP_term_type type, const char *data, char *datatype, char *lang)
+{
 
     LSUP_Term *term;
     CRITICAL (term = malloc (sizeof (*term)));
     term->data = NULL;
     term->datatype = NULL;
 
-    *term_p = term;
+    if (UNLIKELY (LSUP_term_init (
+                    term, type, data, datatype, lang) != LSUP_OK)) {
+        free (term);
+        return NULL;
+    }
+
+    return term;
+}
+
+
+LSUP_Term *
+LSUP_term_new_from_buffer(const LSUP_Buffer *sterm)
+{
+    LSUP_Term *term;
+    CRITICAL (term = malloc (sizeof (*term)));
+    if (UNLIKELY (LSUP_term_deserialize (sterm, term) != LSUP_OK)) {
+        free (term);
+        return NULL;
+    }
+
+    return term;
+}
+
+
+LSUP_Buffer *
+LSUP_buffer_new_from_term(const LSUP_Term *term)
+{
+    LSUP_Buffer *sterm;
+    CRITICAL(sterm = malloc (sizeof (*sterm)));
+    sterm->addr = NULL;
 
-    return LSUP_term_reset(term, type, data, datatype, lang);
+    if (LSUP_term_serialize (term, sterm) != LSUP_OK) {
+        free (sterm);
+        return NULL;
+    }
+
+    return sterm;
 }
 
 
 LSUP_rc
-LSUP_term_reset(
+LSUP_term_init(
         LSUP_Term *term, LSUP_term_type type,
         const char *data, char *datatype, char *lang)
 {
@@ -74,7 +109,7 @@ LSUP_term_reset(
         memset(term->lang, 0, LANG_SIZE);
     }
 
-    return 0;
+    return LSUP_OK;
 }
 
 
@@ -118,15 +153,12 @@ LSUP_term_reset(
  * type   data        datatype         lang
  */
 LSUP_rc
-LSUP_term_serialize(const LSUP_Term *term, LSUP_Buffer **sterm_p)
+LSUP_term_serialize(const LSUP_Term *term, LSUP_Buffer *sterm)
 {
     size_t size, data_len, datatype_len,
            data_idx, datatype_idx, lang_idx;
 
-    if (UNLIKELY (term == NULL)) {
-        *sterm_p = NULL;
-        return LSUP_NOACTION;
-    }
+    if (UNLIKELY (term == NULL)) return LSUP_NOACTION;
 
     data_idx = 1;
     data_len = strlen (term->data) + 1;
@@ -145,8 +177,7 @@ LSUP_term_serialize(const LSUP_Term *term, LSUP_Buffer **sterm_p)
     }
 
     //TRACE("Serialized term size: %lu", size);
-    LSUP_Buffer *sterm;
-    LSUP_buffer_new (size, &sterm);
+    LSUP_buffer_init (sterm, size, NULL);
 
     // Copy type.
     memcpy (sterm->addr, &term->type, 1);
@@ -157,20 +188,17 @@ LSUP_term_serialize(const LSUP_Term *term, LSUP_Buffer **sterm_p)
         // Copy data type.
         memcpy (sterm->addr + datatype_idx, term->datatype, datatype_len);
 
-        if (strlen(term->lang) > 0) {
-            // Copy lang tag.
+        // Copy lang tag.
+        if (strlen (term->lang) > 0)
             memcpy (sterm->addr + lang_idx, term->lang, LANG_SIZE);
-        }
     }
 
-    *sterm_p = sterm;
-
     return LSUP_OK;
 }
 
 
 LSUP_rc
-LSUP_term_deserialize(const LSUP_Buffer *sterm, LSUP_Term **term)
+LSUP_term_deserialize(const LSUP_Buffer *sterm, LSUP_Term *term)
 {
     size_t cur;
     char *data, *datatype = NULL;
@@ -182,7 +210,7 @@ LSUP_term_deserialize(const LSUP_Buffer *sterm, LSUP_Term **term)
     data = (char*)sterm->addr + cur;
     cur += strlen(data) + 1;
 
-    if (type == LSUP_TERM_LITERAL) {
+    if (type == LSUP_TERM_LITERAL && cur < sterm->size) {
         datatype = (char*)sterm->addr + cur;
         cur += strlen(datatype) + 1;
         if (strlen(datatype) == 0)
@@ -192,9 +220,7 @@ LSUP_term_deserialize(const LSUP_Buffer *sterm, LSUP_Term **term)
             strcpy(lang, sterm->addr + cur);
     }
 
-    LSUP_term_new(type, data, datatype, lang, term);
-
-    return LSUP_OK;
+    return LSUP_term_init(term, type, data, datatype, lang);
 }
 
 

+ 9 - 9
src/triple.c

@@ -1,8 +1,8 @@
 #include "triple.h"
 
 // Extern inline prototypes.
-LSUP_Term *LSUP_triple_pos(const LSUP_Triple *trp, LSUP_TriplePos n);
-LSUP_Buffer *LSUP_striple_pos(const LSUP_SerTriple *trp, LSUP_TriplePos n);
+LSUP_Term *LSUP_triple_pos (const LSUP_Triple *trp, LSUP_TriplePos n);
+LSUP_Buffer *LSUP_striple_pos (const LSUP_SerTriple *trp, LSUP_TriplePos n);
 
 
 LSUP_rc
@@ -12,9 +12,9 @@ LSUP_triple_serialize(const LSUP_Triple *spo, LSUP_SerTriple *sspo)
 
     rc = LSUP_term_serialize(spo->s, sspo->s);
     if (UNLIKELY(rc != LSUP_OK)) return rc;
-    rc = LSUP_term_serialize(spo->s, sspo->s);
+    rc = LSUP_term_serialize(spo->p, sspo->p);
     if (UNLIKELY(rc != LSUP_OK)) return rc;
-    rc = LSUP_term_serialize(spo->s, sspo->s);
+    rc = LSUP_term_serialize(spo->o, sspo->o);
     if (UNLIKELY(rc != LSUP_OK)) return rc;
 
     return LSUP_OK;
@@ -28,9 +28,9 @@ LSUP_triple_deserialize(const LSUP_SerTriple *sspo, LSUP_Triple *spo)
 
     rc = LSUP_term_deserialize(sspo->s, spo->s);
     if (UNLIKELY(rc != LSUP_OK)) return rc;
-    rc = LSUP_term_deserialize(sspo->s, spo->s);
+    rc = LSUP_term_deserialize(sspo->p, spo->p);
     if (UNLIKELY(rc != LSUP_OK)) return rc;
-    rc = LSUP_term_deserialize(sspo->s, spo->s);
+    rc = LSUP_term_deserialize(sspo->o, spo->o);
     if (UNLIKELY(rc != LSUP_OK)) return rc;
 
     return LSUP_OK;
@@ -42,9 +42,9 @@ LSUP_triple_done(LSUP_Triple *spo)
 {
     if (UNLIKELY(!spo)) return;
 
-    LSUP_term_free(spo->s);
-    LSUP_term_free(spo->p);
-    LSUP_term_free(spo->o);
+    LSUP_term_done(spo->s);
+    LSUP_term_done(spo->p);
+    LSUP_term_done(spo->o);
 }
 
 

+ 26 - 26
test/assets.h

@@ -12,35 +12,35 @@ LSUP_Triple *create_triples()
 
     // These constitute overall 10 individual triples, 8 unique.
 
-    LSUP_uri_new("urn:s:0", trp[0].s);
-    LSUP_uri_new("urn:p:0", trp[0].p);
-    LSUP_uri_new("urn:o:0", trp[0].o);
+    LSUP_uri_init(trp[0].s, "urn:s:0");
+    LSUP_uri_init(trp[0].p, "urn:p:0");
+    LSUP_uri_init(trp[0].o, "urn:o:0");
 
-    LSUP_uri_new("urn:s:1", trp[1].s);
-    LSUP_uri_new("urn:p:1", trp[1].p);
-    LSUP_uri_new("urn:o:1", trp[1].o);
+    LSUP_uri_init(trp[1].s, "urn:s:1");
+    LSUP_uri_init(trp[1].p, "urn:p:1");
+    LSUP_uri_init(trp[1].o, "urn:o:1");
 
-    LSUP_uri_new("urn:s:2", trp[2].s);
-    LSUP_uri_new("urn:p:2", trp[2].p);
-    LSUP_uri_new("urn:o:2", trp[2].o);
+    LSUP_uri_init(trp[2].s, "urn:s:2");
+    LSUP_uri_init(trp[2].p, "urn:p:2");
+    LSUP_uri_init(trp[2].o, "urn:o:2");
 
-    LSUP_uri_new("urn:s:0", trp[3].s);
-    LSUP_uri_new("urn:p:1", trp[3].p);
-    LSUP_uri_new("urn:o:2", trp[3].o);
+    LSUP_uri_init(trp[3].s, "urn:s:0");
+    LSUP_uri_init(trp[3].p, "urn:p:1");
+    LSUP_uri_init(trp[3].o, "urn:o:2");
 
-    LSUP_uri_new("urn:s:0", trp[4].s);
-    LSUP_uri_new("urn:p:2", trp[4].p);
-    LSUP_term_new(LSUP_TERM_LITERAL, "String 1", NULL, NULL, trp[4].o);
+    LSUP_uri_init(trp[4].s, "urn:s:0");
+    LSUP_uri_init(trp[4].p, "urn:p:2");
+    LSUP_term_init(trp[4].o, LSUP_TERM_LITERAL, "String 1", NULL, NULL);
 
-    LSUP_uri_new("urn:s:0", trp[5].s);
-    LSUP_uri_new("urn:p:5", trp[5].p);
-    LSUP_term_new(
-            LSUP_TERM_LITERAL, "String 1", "xsd:string", NULL, trp[5].o);
+    LSUP_uri_init(trp[5].s, "urn:s:0");
+    LSUP_uri_init(trp[5].p, "urn:p:5");
+    LSUP_term_init(
+            trp[5].o, LSUP_TERM_LITERAL, "String 1", "xsd:string", NULL);
 
-    LSUP_uri_new("urn:s:1", trp[6].s);
-    LSUP_uri_new("urn:p:6", trp[6].p);
-    LSUP_term_new(
-            LSUP_TERM_LITERAL, "String 1", "xsd:string", "es-ES", trp[6].o);
+    LSUP_uri_init(trp[6].s, "urn:s:1");
+    LSUP_uri_init(trp[6].p, "urn:p:6");
+    LSUP_term_init(
+            trp[6].o, LSUP_TERM_LITERAL, "String 1", "xsd:string", "es-ES");
 
     // Let's reuse pointers. Do not double-free.
     trp[7].s = trp[0].s; // <urn:s:0>
@@ -66,9 +66,9 @@ void free_triples(LSUP_Triple *trp)
 {
     // Last three triples are second pointers.
     for(int i=0; i < NUM_TRP - 3; i++) {
-        LSUP_term_free(trp[i].s);
-        LSUP_term_free(trp[i].p);
-        LSUP_term_free(trp[i].o);
+        LSUP_term_done(trp[i].s);
+        LSUP_term_done(trp[i].p);
+        LSUP_term_done(trp[i].o);
     }
 
     free(trp);

+ 2 - 3
test/test_graph.c

@@ -5,7 +5,7 @@
 static int test_graph_new()
 {
     LSUP_Graph *gr;
-    EXPECT_PASS(LSUP_graph_new(LSUP_STORE_MEM, &gr));
+    gr = LSUP_graph_new(LSUP_STORE_MEM);
 
     EXPECT_PASS(LSUP_graph_set_uri(gr, "urn:gr:1"));
     EXPECT_STR_EQ(LSUP_graph_uri(gr)->data, "urn:gr:1");
@@ -26,8 +26,7 @@ static int test_graph_add()
 {
     LSUP_Triple *trp = create_triples();
 
-    LSUP_Graph *gr;
-    LSUP_graph_new(LSUP_STORE_MEM, &gr);
+    LSUP_Graph *gr = LSUP_graph_new(LSUP_STORE_MEM);
     LSUP_graph_resize(gr, NUM_TRP + 2);
 
     size_t ct;

+ 18 - 18
test/test_htable.c

@@ -14,25 +14,25 @@ static int htable_idx()
 {
     LSUP_Key keys[_CT] = {5, 8, 13, 21, 34, 55, 89, 5};
 
-    LSUP_HTable *ht;
-    LSUP_htable_new(
+    LSUP_HTable *ht = LSUP_htable_new(
             _CT, sizeof(LSUP_Key), sizeof(LSUP_Buffer),
-            id_hash_fn, buffer_eq_fn, &ht);
+            id_hash_fn, buffer_eq_fn);
 
-    LSUP_Buffer values[_CT];
+    LSUP_Buffer *sterm = BUF_DUMMY;
 
     for (int i = 0; i < _CT; i++) {
         char tmp[64];
         sprintf(tmp, "<%lu>", keys[i]);
-        LSUP_buffer_init(values + i, strlen(tmp) + 1);
-        memcpy((values + i)->addr, tmp, strlen(tmp) + 1);
+        LSUP_buffer_reset(sterm, strlen(tmp) + 1, tmp);
         printf("Buffer to insert: ");
-        LSUP_buffer_print(values + i);
+        LSUP_buffer_print(sterm);
 
-        if (LSUP_htable_put(ht, keys + i, values + i) != LSUP_OK)
-            LSUP_buffer_done(values + i);
+        if (LSUP_htable_put(ht, keys + i, sterm) != LSUP_OK)
+            LSUP_buffer_done(sterm);
     }
 
+    LSUP_buffer_free(sterm);
+
     EXPECT_INT_EQ(LSUP_htable_size(ht), 7);
 
     for (int i = 0; i < _CT; i++) {
@@ -87,25 +87,25 @@ static int htable_keys()
         {2, 1, 1}, // Duplicate.
     };
 
-    LSUP_HTable *ht;
-    LSUP_htable_new(
+    LSUP_HTable *ht = LSUP_htable_new(
             _CT, sizeof(LSUP_TripleKey), sizeof(LSUP_Buffer),
-            id_hash_fn, buffer_eq_fn, &ht);
+            id_hash_fn, buffer_eq_fn);
 
-    LSUP_Buffer values[_CT];
+    LSUP_Buffer *sterm = BUF_DUMMY;
 
     for (int i = 0; i < _CT; i++) {
         char tmp[64];
         sprintf(tmp, "<%lu : %lu : %lu>", keys[i][0], keys[i][1], keys[i][2]);
-        LSUP_buffer_init(values + i, strlen(tmp) + 1);
-        memcpy((values + i)->addr, tmp, strlen(tmp) + 1);
+        LSUP_buffer_reset(sterm, strlen(tmp) + 1, tmp);
         TRACE(STR, "Buffer to insert: ");
-        LSUP_buffer_print(values + i);
+        LSUP_buffer_print(sterm);
 
-        if (LSUP_htable_put(ht, keys + i, values + i) != LSUP_OK)
-            LSUP_buffer_done(values + i);
+        if (LSUP_htable_put(ht, keys + i, sterm) != LSUP_OK)
+            LSUP_buffer_done(sterm);
     }
 
+    LSUP_buffer_free(sterm);
+
     EXPECT_INT_EQ(LSUP_htable_size(ht), 6);
 
     for (int i = 0; i < _CT; i++) {

+ 11 - 15
test/test_store_mdb.c

@@ -27,8 +27,7 @@ static int test_triple_store()
     rmdb();
     EXPECT_PASS(LSUP_mdbstore_setup(&path));
 
-    LSUP_MDBStore *store;
-    LSUP_mdbstore_new(path, NULL, &store); // triple store.
+    LSUP_MDBStore *store = LSUP_mdbstore_new(path, NULL); // triple store.
     ASSERT(store != NULL, "Error initializing store!");
 
     LSUP_Triple *trp = create_triples();
@@ -98,11 +97,10 @@ static int test_triple_store()
 
     for (int i = 0; i < 12; i++) {
         size_t ct;
-        LSUP_MDBIterator *it;
-
         TRACE("Testing triple lookup #%d.\n", i);
 
-        EXPECT_PASS(LSUP_mdbstore_lookup(store, lut + i, luc[i], &it, &ct));
+        LSUP_MDBIterator *it = LSUP_mdbstore_lookup(
+                store, lut + i, luc[i], &ct);
         EXPECT_INT_EQ(ct, results[i]);
 
         LSUP_mdbiter_free(it);
@@ -130,14 +128,12 @@ static int test_quad_store()
     rmdb();
     EXPECT_PASS(LSUP_mdbstore_setup(&path));
 
-    LSUP_Term *ctx1;
-    LSUP_uri_new("urn:c:1", ctx1);
+    LSUP_Term *ctx1 = LSUP_uri_new("urn:c:1");
     LSUP_Buffer sc1_s;
     LSUP_Buffer *sc1 = &sc1_s;
     LSUP_term_serialize(ctx1, sc1);
 
-    LSUP_MDBStore *store;
-    EXPECT_PASS(LSUP_mdbstore_new(path, sc1, &store)); // quad store.
+    LSUP_MDBStore *store = LSUP_mdbstore_new(path, sc1); // quad store.
     ASSERT(store != NULL, "Error initializing store!");
 
     LSUP_Triple *trp = create_triples();
@@ -160,8 +156,7 @@ static int test_quad_store()
     EXPECT_PASS(LSUP_mdbstore_add(store, NULL, ser_trp, 6, &ct));
     EXPECT_INT_EQ(ct, 6);
 
-    LSUP_Term *ctx2;
-    LSUP_uri_new("urn:c:2", ctx2);
+    LSUP_Term *ctx2 = LSUP_uri_new("urn:c:2");
     LSUP_Buffer sc2_s;
     LSUP_Buffer *sc2 = &sc2_s;
     LSUP_term_serialize(ctx2, sc2);
@@ -175,8 +170,7 @@ static int test_quad_store()
 
     // Test lookups.
     // This context is not with any triple.
-    LSUP_Term *ctx3;
-    LSUP_uri_new("urn:c:3", ctx3);
+    LSUP_Term *ctx3 = LSUP_uri_new("urn:c:3");
     LSUP_Buffer sc3_s;
     LSUP_Buffer *sc3 = &sc3_s;
     LSUP_term_serialize(ctx3, sc3);
@@ -300,7 +294,6 @@ static int test_quad_store()
 
     for (int i = 0; i < 41; i++) {
         size_t ct;
-        LSUP_MDBIterator *it;
 
         printf("Testing triple lookup #%d: {", i);
 
@@ -320,7 +313,9 @@ static int test_quad_store()
         else printf("NULL");
         printf("}\n");
 
-        EXPECT_PASS(LSUP_mdbstore_lookup(store, lut + i, luc[i], &it, &ct));
+        LSUP_MDBIterator *it = LSUP_mdbstore_lookup(
+                store, lut + i, luc[i], &ct);
+        ASSERT(it != NULL, "Lookup error!");
         EXPECT_INT_EQ(ct, results[i]);
 
         LSUP_mdbiter_free(it);
@@ -334,6 +329,7 @@ static int test_quad_store()
 
     LSUP_term_free(ctx1);
     LSUP_term_free(ctx2);
+    LSUP_term_free(ctx3);
     LSUP_buffer_done(&sc1_s);
     LSUP_buffer_done(&sc2_s);
     free_triples(trp);

+ 19 - 26
test/test_term.c

@@ -8,8 +8,7 @@ static int test_term_new()
     char *lang = "en-US";
 
     TRACE(STR, "Test term, heap-allocated.");
-    LSUP_Term *term;
-    LSUP_term_new(LSUP_TERM_LITERAL, data, datatype, lang, term);
+    LSUP_Term *term = LSUP_term_new(LSUP_TERM_LITERAL, data, datatype, lang);
 
     TRACE("Term data: %s", term->data);
     EXPECT_STR_EQ(term->data, data);
@@ -19,7 +18,7 @@ static int test_term_new()
     TRACE(STR, "Reset term.\n");
 
     char *uri_data = "urn:id:2144564356";
-    LSUP_term_reset(term, LSUP_TERM_URI, uri_data, NULL, NULL);
+    LSUP_term_init(term, LSUP_TERM_URI, uri_data, NULL, NULL);
     EXPECT_STR_EQ(term->data, uri_data);
 
     LSUP_term_free(term);
@@ -29,17 +28,14 @@ static int test_term_new()
 
 static int test_term_serialize_deserialize()
 {
-    LSUP_Term *uri, *lit, *tlit, *tllit;
-    LSUP_term_new(LSUP_TERM_URI, "http://hello.org", NULL, NULL, uri);
-    LSUP_term_new(LSUP_TERM_LITERAL, "hello", NULL, NULL, lit);
-    LSUP_term_new(LSUP_TERM_LITERAL, "hello", "xsd:string", NULL, tlit);
-    LSUP_term_new(LSUP_TERM_LITERAL, "hello", "xsd:string", "en-US", tllit);
+    LSUP_Term *uri = LSUP_uri_new("http://hello.org");
+    LSUP_Term *lit = LSUP_term_new(LSUP_TERM_LITERAL, "hello", NULL, NULL);
+    LSUP_Term *tlit = LSUP_term_new(LSUP_TERM_LITERAL, "hello", "xsd:string", NULL);
+    LSUP_Term *tllit = LSUP_term_new(LSUP_TERM_LITERAL, "hello", "xsd:string", "en-US");
 
-    LSUP_Buffer sterm_s;
-    LSUP_Buffer *sterm = &sterm_s;
+    LSUP_Buffer *sterm = LSUP_buffer_new(0, NULL);
 
-    LSUP_Term dsterm_s;
-    LSUP_Term *dsterm = &dsterm_s;
+    LSUP_Term *dsterm = malloc (sizeof (*dsterm));
 
     LSUP_term_serialize(uri, sterm);
     TRACE("%s", "Serialized URI: ");
@@ -47,8 +43,6 @@ static int test_term_serialize_deserialize()
     TRACE("%s", "\n");
     LSUP_term_deserialize(sterm, dsterm);
     ASSERT(LSUP_term_equals(dsterm, uri), "URI serialization error!");
-    LSUP_term_free(dsterm);
-    LSUP_buffer_done(sterm);
     LSUP_term_free(uri);
 
     LSUP_term_serialize(lit, sterm);
@@ -57,8 +51,6 @@ static int test_term_serialize_deserialize()
     TRACE("%s", "\n");
     LSUP_term_deserialize(sterm, dsterm);
     ASSERT(LSUP_term_equals(dsterm, lit), "lit serialization error!");
-    LSUP_term_free(dsterm);
-    LSUP_buffer_done(sterm);
     LSUP_term_free(lit);
 
     LSUP_term_serialize(tlit, sterm);
@@ -67,8 +59,6 @@ static int test_term_serialize_deserialize()
     TRACE("%s", "\n");
     LSUP_term_deserialize(sterm, dsterm);
     ASSERT(LSUP_term_equals(dsterm, tlit), "tlit serialization error!");
-    LSUP_term_free(dsterm);
-    LSUP_buffer_done(sterm);
     LSUP_term_free(tlit);
 
     LSUP_term_serialize(tllit, sterm);
@@ -77,22 +67,25 @@ static int test_term_serialize_deserialize()
     TRACE("%s", "\n");
     LSUP_term_deserialize(sterm, dsterm);
     ASSERT(LSUP_term_equals(dsterm, tllit), "URI serialization error!");
-    LSUP_term_free(dsterm);
-    LSUP_buffer_done(sterm);
     LSUP_term_free(tllit);
 
+    LSUP_term_free(dsterm);
+    LSUP_buffer_free(sterm);
+
     return 0;
 }
 
 
 static int test_term_to_key()
 {
-    LSUP_Term *uri, *lit, *tlit, *tllit1, *tllit2;
-    LSUP_term_new(LSUP_TERM_URI, "http://hello.org", NULL, NULL, uri);
-    LSUP_term_new(LSUP_TERM_LITERAL, "hello", NULL, NULL, lit);
-    LSUP_term_new(LSUP_TERM_LITERAL, "hello", "xsd:string", NULL, tlit);
-    LSUP_term_new(LSUP_TERM_LITERAL, "hello", "xsd:string", "en-US", tllit1);
-    LSUP_term_new(LSUP_TERM_LITERAL, "hello", "xsd:string", "en-GB", tllit2);
+    LSUP_Term *uri = LSUP_uri_new("http://hello.org");
+    LSUP_Term *lit = LSUP_term_new(LSUP_TERM_LITERAL, "hello", NULL, NULL);
+    LSUP_Term *tlit = LSUP_term_new(
+            LSUP_TERM_LITERAL, "hello", "xsd:string", NULL);
+    LSUP_Term *tllit1 = LSUP_term_new(
+            LSUP_TERM_LITERAL, "hello", "xsd:string", "en-US");
+    LSUP_Term *tllit2 = LSUP_term_new(
+            LSUP_TERM_LITERAL, "hello", "xsd:string", "en-GB");
 
     LSUP_Key uri_key = LSUP_term_to_key(uri);
     LSUP_Key lit_key = LSUP_term_to_key(lit);