Browse Source

faux: Unfinished list

Serj Kalichev 4 years ago
parent
commit
cb48b4b99c
6 changed files with 294 additions and 208 deletions
  1. 5 5
      faux/Makefile.am
  2. 47 46
      faux/list.h
  3. 3 0
      faux/list/Makefile.am
  4. 229 142
      faux/list/list.c
  5. 0 5
      faux/list/module.am
  6. 10 10
      faux/list/private.h

+ 5 - 5
faux/Makefile.am

@@ -8,10 +8,10 @@ nobase_include_HEADERS += \
 	faux/str.h \
 	faux/sysdb.h \
 	faux/conv.h \
-	faux/log.h
+	faux/log.h \
+	faux/list.h
 
 #	faux/argv.h \
-#	faux/list.h \
 #	faux/dump.h \
 #	faux/system.h \
 #	faux/ini.h
@@ -21,10 +21,10 @@ EXTRA_DIST += \
 	faux/str/Makefile.am \
 	faux/sysdb/Makefile.am \
 	faux/conv/Makefile.am \
-	faux/log/module.am
+	faux/log/module.am \
+	faux/list/module.am
 
 #	faux/argv/module.am \
-#	faux/list/module.am \
 #	faux/dump/module.am \
 #	faux/system/module.am \
 #	faux/ini/module.am \
@@ -36,9 +36,9 @@ include $(top_srcdir)/faux/str/Makefile.am
 include $(top_srcdir)/faux/sysdb/Makefile.am
 include $(top_srcdir)/faux/conv/Makefile.am
 include $(top_srcdir)/faux/log/Makefile.am
+include $(top_srcdir)/faux/list/Makefile.am
 
 #include $(top_srcdir)/faux/argv/module.am
-#include $(top_srcdir)/faux/list/module.am
 #include $(top_srcdir)/faux/dump/module.am
 #include $(top_srcdir)/faux/system/module.am
 #include $(top_srcdir)/faux/ini/module.am

+ 47 - 46
faux/list.h

@@ -1,51 +1,52 @@
-#ifndef _lub_list_h
-#define _lub_list_h
+#ifndef _faux_list_h
+#define _faux_list_h
 
 #include <stddef.h>
-#include "lub/c_decl.h"
+
 #include "types.h"
 
-typedef struct lub_list_node_s lub_list_node_t;
-typedef int lub_list_compare_fn(const void *first, const void *second);
-typedef void lub_list_free_fn(void *data);
-typedef int lub_list_match_fn(const void *key, const void *data);
-typedef struct lub_list_s lub_list_t;
-typedef struct lub_list_node_s lub_list_iterator_t;
-
-_BEGIN_C_DECL
-
-lub_list_node_t *lub_list_node_new(void *data);
-lub_list_node_t *lub_list_node__get_prev(lub_list_node_t *node);
-lub_list_node_t *lub_list_node__get_next(lub_list_node_t *node);
-void *lub_list_node__get_data(lub_list_node_t *node);
-void lub_list_node_free(lub_list_node_t *node);
-void lub_list_node_copy(lub_list_node_t *dst, lub_list_node_t *src);
-
-lub_list_t *lub_list_new(lub_list_compare_fn compareFn,
-	lub_list_free_fn freeFn);
-void lub_list_free(lub_list_t *list);
-void lub_list_free_all(lub_list_t *list);
-lub_list_node_t *lub_list__get_head(lub_list_t *list);
-lub_list_node_t *lub_list__get_tail(lub_list_t *list);
-lub_list_node_t *lub_list_iterator_init(lub_list_t *list);
-lub_list_node_t *lub_list_iterator_next(lub_list_node_t *node);
-lub_list_node_t *lub_list_iterator_prev(lub_list_node_t *node);
-lub_list_node_t *lub_list_add(lub_list_t *list, void *data);
-lub_list_node_t *lub_list_add_uniq(lub_list_t *list, void *data);
-lub_list_node_t *lub_list_find_add(lub_list_t *list, void *data);
-void lub_list_del(lub_list_t *list, lub_list_node_t *node);
-unsigned int lub_list_len(lub_list_t *list);
-lub_list_node_t *lub_list_match_node(lub_list_t *list,
-	lub_list_match_fn matchFn, const void *userkey,
-	lub_list_node_t **saveptr);
-void *lub_list_find_node(lub_list_t *list,
-	lub_list_match_fn matchFn, const void *userkey);
-void *lub_list_match(lub_list_t *list,
-	lub_list_match_fn matchFn, const void *userkey,
-	lub_list_node_t **saveptr);
-void *lub_list_find(lub_list_t *list,
-	lub_list_match_fn matchFn, const void *userkey);
-
-_END_C_DECL
-#endif				/* _lub_list_h */
+typedef struct faux_list_node_s faux_list_node_t;
+typedef struct faux_list_s faux_list_t;
+
+typedef int faux_list_compare_fn(const void *first, const void *second);
+typedef void faux_list_free_fn(void *data);
+typedef int faux_list_match_fn(const void *key, const void *data);
+
+C_DECL_BEGIN
+
+// list_node_t methods
+faux_list_node_t *faux_list_prev_node(const faux_list_node_t *node);
+faux_list_node_t *faux_list_next_node(const faux_list_node_t *node);
+void *faux_list_data(const faux_list_node_t *node);
+faux_list_node_t *faux_list_each_node(faux_list_node_t **iter);
+void *faux_list_each(faux_list_node_t **iter);
+
+// list_t methods
+faux_list_t *faux_list_new(faux_list_compare_fn compareFn,
+	faux_list_free_fn freeFn);
+void faux_list_free(faux_list_t *list);
+
+faux_list_node_t *faux_list_head(faux_list_t *list);
+faux_list_node_t *faux_list_tail(faux_list_t *list);
+size_t faux_list_len(faux_list_t *list);
+
+faux_list_node_t *faux_list_add(faux_list_t *list, void *data);
+faux_list_node_t *faux_list_add_uniq(faux_list_t *list, void *data);
+faux_list_node_t *faux_list_find_add(faux_list_t *list, void *data);
+void faux_list_del(faux_list_t *list, faux_list_node_t *node);
+
+faux_list_node_t *faux_list_match_node(faux_list_t *list,
+	faux_list_match_fn matchFn, const void *userkey,
+	faux_list_node_t **saveptr);
+void *faux_list_match(faux_list_t *list,
+	faux_list_match_fn matchFn, const void *userkey,
+	faux_list_node_t **saveptr);
+faux_list_node_t *faux_list_find_node(faux_list_t *list,
+	faux_list_match_fn matchFn, const void *userkey);
+void *faux_list_find(faux_list_t *list,
+	faux_list_match_fn matchFn, const void *userkey);
+
+C_DECL_END
+
+#endif				/* _faux_list_h */
 

+ 3 - 0
faux/list/Makefile.am

@@ -0,0 +1,3 @@
+libfaux_la_SOURCES += \
+	faux/list/list.c \
+	faux/list/private.h

+ 229 - 142
faux/list/list.c

@@ -1,144 +1,219 @@
+/** @file list.c
+ * @brief Implementation of a bidirectional list.
+ *
+ * Bidirectional List stores special structures (nodes) as its elements.
+ * Nodes are linked to each other. Node stores abstract user data (i.e. void *).
+ *
+ * List can be sorted or unsorted. To sort list user provides special callback
+ * function to compare two nodes. The list will be sorted
+ * due to this function return value that indicates "less than",
+ * "equal", "greater than". Additionally user may provide another callback
+ * function to free user defined data on list freeing.
+ */
+
 #include <stdlib.h>
 #include <assert.h>
 #include <string.h>
 
 #include "private.h"
+#include "faux/list.h"
 
-/*--------------------------------------------------------- */
-static void lub_list_init(lub_list_t *this,
-	lub_list_compare_fn compareFn,
-	lub_list_free_fn freeFn)
-{
-	this->head = NULL;
-	this->tail = NULL;
-	this->compareFn = compareFn;
-	this->freeFn = freeFn;
-	this->len = 0;
-}
 
-/*--------------------------------------------------------- */
-lub_list_t *lub_list_new(lub_list_compare_fn compareFn,
-	lub_list_free_fn freeFn)
-{
-	lub_list_t *this;
+/** @brief Allocates and initializes new list node instance.
+ *
+ * @param [in] data User defined data to store within node.
+ * @return Newly created list node instance or NULL on error.
+ */
+static faux_list_node_t *faux_list_new_node(void *data) {
 
-	this = malloc(sizeof(*this));
-	assert(this);
-	lub_list_init(this, compareFn, freeFn);
+	faux_list_node_t *node = NULL;
 
-	return this;
-}
+	node = malloc(sizeof(*node));
+	assert(node);
+	if (!node)
+		return NULL;
 
-/*--------------------------------------------------------- */
-inline void lub_list_free(lub_list_t *this)
-{
-	free(this);
+	// Initialize
+	node->prev = NULL;
+	node->next = NULL;
+	node->data = data;
+
+	return node;
 }
 
-/*--------------------------------------------------------- */
-/* Free all nodes and data from list and finally
- * free the list itself. It uses special callback
- * function specified by user to free the abstract
- * data.
+
+/** @brief Free list node instance.
+ *
+ * @param [in] node List node instance.
  */
-void lub_list_free_all(lub_list_t *this)
-{
-	lub_list_node_t *iter;
-
-	while ((iter = lub_list__get_head(this))) {
-		lub_list_del(this, iter);
-		if (this->freeFn)
-			this->freeFn(lub_list_node__get_data(iter));
-		lub_list_node_free(iter);
-	}
-	lub_list_free(this);
-}
+static void faux_list_free_node(faux_list_node_t *node) {
 
-/*--------------------------------------------------------- */
-inline lub_list_node_t *lub_list__get_head(lub_list_t *this)
-{
-	return this->head;
+	assert(node);
+
+	if (node)
+		free(node);
 }
 
-/*--------------------------------------------------------- */
-inline lub_list_node_t *lub_list__get_tail(lub_list_t *this)
-{
-	return this->tail;
+
+/** @brief Gets previous list node.
+ *
+ * @param [in] this List node instance.
+ * @return List node previous in list.
+ */
+faux_list_node_t *faux_list_prev_node(const faux_list_node_t *node) {
+
+	assert(node);
+	if (!node)
+		return NULL;
+
+	return node->prev;
 }
 
-/*--------------------------------------------------------- */
-static void lub_list_node_init(lub_list_node_t *this,
-	void *data)
-{
-	this->prev = this->next = NULL;
-	this->data = data;
+
+/** @brief Gets next list node.
+ *
+ * @param [in] this List node instance.
+ * @return List node next in list.
+ */
+faux_list_node_t *faux_list_next_node(const faux_list_node_t *node) {
+
+	assert(node);
+	if (!node)
+		return NULL;
+
+	return node->next;
 }
 
-/*--------------------------------------------------------- */
-lub_list_node_t *lub_list_node_new(void *data)
-{
-	lub_list_node_t *this;
 
-	this = malloc(sizeof(*this));
-	assert(this);
-	lub_list_node_init(this, data);
+/** @brief Gets user data from list node.
+ *
+ * @param [in] this List node instance.
+ * @return User data stored within specified list node.
+ */
+void *faux_list_data(const faux_list_node_t *node) {
+
+	assert(node);
+	if (!node)
+		return NULL;
 
-	return this;
+	return node->data;
 }
 
-/*--------------------------------------------------------- */
-inline lub_list_node_t *lub_list_iterator_init(lub_list_t *this)
-{
-	return this->head;
+
+/** @brief Iterate through each list node.
+ *
+ * On each call to this function the iterator will change its value.
+ * Before function using the iterator must be initialised by list head node.
+ *
+ * @param [in,out] iter List node ptr used as an iterator.
+ * @return List node or NULL if list elements are over.
+ */
+faux_list_node_t *faux_list_each_node(faux_list_node_t **iter) {
+
+	faux_list_node_t *current_node = *iter;
+
+	if (!current_node)
+		return NULL;
+	*iter = faux_list_next_node(current_node);
+
+	return current_node;
 }
 
-/*--------------------------------------------------------- */
-inline lub_list_node_t *lub_list_node__get_prev(lub_list_node_t *this)
-{
-	return this->prev;
+
+/** @brief Iterate through each list node and returns user data.
+ *
+ * On each call to this function the iterator will change its value.
+ * Before function using the iterator must be initialised by list head node.
+ *
+ * @param [in,out] iter List node ptr used as an iterator.
+ * @return User data or NULL if list elements are over.
+ */
+void *faux_list_each(faux_list_node_t **iter) {
+
+	faux_list_node_t *current_node = NULL;
+
+	if (!*iter)
+		return NULL;
+	current_node = faux_list_each_node(iter);
+
+	return faux_list_data(current_node);
 }
 
-/*--------------------------------------------------------- */
-inline lub_list_node_t *lub_list_node__get_next(lub_list_node_t *this)
-{
-	return this->next;
+
+/** @brief Allocate and initialize bidirectional list.
+ *
+ * @param [in] compareFn Callback function to compare two user data instances
+ * to sort list.
+ * @param [in] freeFn Callback function to free user data.
+ * @return Newly created bidirectional list or NULL on error.
+ */
+faux_list_t *faux_list_new(faux_list_compare_fn compareFn,
+	faux_list_free_fn freeFn) {
+
+	faux_list_t *list;
+
+	list = malloc(sizeof(*list));
+	assert(list);
+	if (!list)
+		return NULL;
+
+	// Initialize
+	list->head = NULL;
+	list->tail = NULL;
+	list->compareFn = compareFn;
+	list->freeFn = freeFn;
+	list->len = 0;
+
+	return list;
 }
 
-/*--------------------------------------------------------- */
-inline lub_list_node_t *lub_list_iterator_next(lub_list_node_t *this)
-{
-	return lub_list_node__get_next(this);
+
+/** @brief Free bidirectional list
+ *
+ * Free all nodes and user data from list and finally
+ * free the list itself. It uses special callback
+ * function specified by user (while faux_list_new()) to free the abstract
+ * user data.
+ *
+ * @param [in] list List to free.
+ */
+void faux_list_free(faux_list_t *list) {
+
+	faux_list_node_t *iter;
+
+	while ((iter = faux_list_head(list))) {
+		faux_list_del(list, iter);
+	}
+	free(list);
 }
 
 /*--------------------------------------------------------- */
-inline lub_list_node_t *lub_list_iterator_prev(lub_list_node_t *this)
-{
-	return lub_list_node__get_prev(this);
+faux_list_node_t *faux_list_head(faux_list_t *this) {
+	return this->head;
 }
 
 /*--------------------------------------------------------- */
-inline void lub_list_node_free(lub_list_node_t *this)
-{
-	free(this);
+faux_list_node_t *faux_list_tail(faux_list_t *this) {
+	return this->tail;
 }
 
 /*--------------------------------------------------------- */
-inline void *lub_list_node__get_data(lub_list_node_t *this)
-{
-	return this->data;
+size_t faux_list_len(faux_list_t *this) {
+	return this->len;
 }
 
+
+
 /*--------------------------------------------------------- */
 /* uniq - true/false Don't add entry with identical order
  *	key (when the compareFn() returns 0)
  * find - true/false Function returns list_node if there is
  *	identical entry. Or NULL if find is false.
  */
-static lub_list_node_t *lub_list_add_generic(lub_list_t *this, void *data,
-	bool_t uniq, bool_t find)
-{
-	lub_list_node_t *node = lub_list_node_new(data);
-	lub_list_node_t *iter;
+static faux_list_node_t *faux_list_add_generic(faux_list_t *this, void *data,
+	bool_t uniq, bool_t find) {
+	faux_list_node_t *node = faux_list_new_node(data);
+	faux_list_node_t *iter;
 
 	this->len++;
 
@@ -162,8 +237,9 @@ static lub_list_node_t *lub_list_add_generic(lub_list_t *this, void *data,
 	iter = this->tail;
 	while (iter) {
 		int res = this->compareFn(node->data, iter->data);
+
 		if (uniq && (res == 0)) {
-			this->len--; // Revert previous increment
+			this->len--;	// Revert previous increment
 			return (find ? iter : NULL);
 		}
 		if (res >= 0) {
@@ -190,50 +266,68 @@ static lub_list_node_t *lub_list_add_generic(lub_list_t *this, void *data,
 }
 
 /*--------------------------------------------------------- */
-lub_list_node_t *lub_list_add(lub_list_t *this, void *data)
-{
-	return lub_list_add_generic(this, data, BOOL_FALSE, BOOL_FALSE);
+faux_list_node_t *faux_list_add(faux_list_t *this, void *data) {
+	return faux_list_add_generic(this, data, BOOL_FALSE, BOOL_FALSE);
 }
 
 /*--------------------------------------------------------- */
-lub_list_node_t *lub_list_add_uniq(lub_list_t *this, void *data)
-{
-	return lub_list_add_generic(this, data, BOOL_TRUE, BOOL_FALSE);
+faux_list_node_t *faux_list_add_uniq(faux_list_t *this, void *data) {
+	return faux_list_add_generic(this, data, BOOL_TRUE, BOOL_FALSE);
 }
 
 /*--------------------------------------------------------- */
-lub_list_node_t *lub_list_find_add(lub_list_t *this, void *data)
-{
-	return lub_list_add_generic(this, data, BOOL_TRUE, BOOL_TRUE);
+faux_list_node_t *faux_list_find_add(faux_list_t *this, void *data) {
+	return faux_list_add_generic(this, data, BOOL_TRUE, BOOL_TRUE);
 }
 
-/*--------------------------------------------------------- */
-void lub_list_del(lub_list_t *this, lub_list_node_t *node)
-{
+
+void *faux_list_takeaway(faux_list_t *list, faux_list_node_t *node) {
+
+	void *data = NULL;
+
+	assert(list);
+	assert(node);
+	if (!list || !node)
+		return NULL;
+
 	if (node->prev)
 		node->prev->next = node->next;
 	else
-		this->head = node->next;
+		list->head = node->next;
 	if (node->next)
 		node->next->prev = node->prev;
 	else
-		this->tail = node->prev;
+		list->tail = node->prev;
+	list->len--;
 
-	this->len--;
+	data = faux_list_data(node);
+	faux_list_free_node(node);
+
+	return data;
 }
 
 /*--------------------------------------------------------- */
-inline void lub_list_node_copy(lub_list_node_t *dst, lub_list_node_t *src)
-{
-	memcpy(dst, src, sizeof(lub_list_node_t));
+void faux_list_del(faux_list_t *list, faux_list_node_t *node) {
+
+	void *data = NULL;
+
+	assert(list);
+	assert(node);
+	if (!list || !node)
+		return;
+
+	data = faux_list_takeaway(list, node);
+	if (list->freeFn)
+		list->freeFn(data);
 }
 
+
 /*--------------------------------------------------------- */
-lub_list_node_t *lub_list_match_node(lub_list_t *this,
-	lub_list_match_fn matchFn, const void *userkey,
-	lub_list_node_t **saveptr)
-{
-	lub_list_node_t *iter = NULL;
+faux_list_node_t *faux_list_match_node(faux_list_t *this,
+	faux_list_match_fn matchFn, const void *userkey,
+	faux_list_node_t **saveptr) {
+	faux_list_node_t *iter = NULL;
+
 	if (!this || !matchFn || !this->head)
 		return NULL;
 	if (saveptr)
@@ -242,14 +336,15 @@ lub_list_node_t *lub_list_match_node(lub_list_t *this,
 		iter = this->head;
 	while (iter) {
 		int res;
-		lub_list_node_t *node = iter;
-		iter = lub_list_node__get_next(iter);
+		faux_list_node_t *node = iter;
+
+		iter = faux_list_next_node(iter);
 		if (saveptr)
 			*saveptr = iter;
-		res = matchFn(userkey, lub_list_node__get_data(node));
+		res = matchFn(userkey, faux_list_data(node));
 		if (!res)
 			return node;
-		if (res < 0) // No chances to find match
+		if (res < 0)	// No chances to find match
 			return NULL;
 	}
 
@@ -257,32 +352,24 @@ lub_list_node_t *lub_list_match_node(lub_list_t *this,
 }
 
 /*--------------------------------------------------------- */
-void *lub_list_find_node(lub_list_t *this,
-	lub_list_match_fn matchFn, const void *userkey)
-{
-	return lub_list_match_node(this, matchFn, userkey, NULL);
+faux_list_node_t *faux_list_find_node(faux_list_t *this,
+	faux_list_match_fn matchFn, const void *userkey) {
+	return faux_list_match_node(this, matchFn, userkey, NULL);
 }
 
 /*--------------------------------------------------------- */
-void *lub_list_match(lub_list_t *this,
-	lub_list_match_fn matchFn, const void *userkey,
-	lub_list_node_t **saveptr)
-{
-	lub_list_node_t *res = lub_list_match_node(this, matchFn, userkey, saveptr);
+void *faux_list_match(faux_list_t *this,
+	faux_list_match_fn matchFn, const void *userkey,
+	faux_list_node_t **saveptr) {
+	faux_list_node_t *res =
+		faux_list_match_node(this, matchFn, userkey, saveptr);
 	if (!res)
 		return NULL;
-	return lub_list_node__get_data(res);
+	return faux_list_data(res);
 }
 
 /*--------------------------------------------------------- */
-void *lub_list_find(lub_list_t *this,
-	lub_list_match_fn matchFn, const void *userkey)
-{
-	return lub_list_match(this, matchFn, userkey, NULL);
-}
-
-/*--------------------------------------------------------- */
-inline unsigned int lub_list_len(lub_list_t *this)
-{
-	return this->len;
+void *faux_list_find(faux_list_t *this,
+	faux_list_match_fn matchFn, const void *userkey) {
+	return faux_list_match(this, matchFn, userkey, NULL);
 }

+ 0 - 5
faux/list/module.am

@@ -1,5 +0,0 @@
-## Process this file with automake to produce Makefile.in
-liblub_la_SOURCES += \
-	lub/list/list.c \
-	lub/list/private.h
-

+ 10 - 10
faux/list/private.h

@@ -1,15 +1,15 @@
-#include "lub/list.h"
+#include "faux/list.h"
 
-struct lub_list_node_s {
-	lub_list_node_t *prev;
-	lub_list_node_t *next;
+struct faux_list_node_s {
+	faux_list_node_t *prev;
+	faux_list_node_t *next;
 	void *data;
 };
 
-struct lub_list_s {
-	lub_list_node_t *head;
-	lub_list_node_t *tail;
-	lub_list_compare_fn *compareFn; // Function to compare two list elements
-	lub_list_free_fn *freeFn; // Function to properly free data field
-	unsigned int len;
+struct faux_list_s {
+	faux_list_node_t *head;
+	faux_list_node_t *tail;
+	faux_list_compare_fn *compareFn; // Function to compare two list elements
+	faux_list_free_fn *freeFn; // Function to properly free data field
+	size_t len;
 };