Browse Source

UNFINISHED: lub_list changes

Serj Kalichev 1 year ago
parent
commit
760c9ef063

+ 2 - 7
bin/clish.c

@@ -129,7 +129,7 @@ int main(int argc, char **argv)
 #endif
 
 	/* Var initialization */
-	cmds = lub_list_new(NULL);
+	cmds = lub_list_new(NULL, free);
 
 	/* Parse command line options */
 	while(1) {
@@ -374,12 +374,7 @@ end:
 		fclose(outfd);
 
 	/* Delete each cmds element */
-	while ((iter = lub_list__get_head(cmds))) {
-		lub_list_del(cmds, iter);
-		free(lub_list_node__get_data(iter));
-		lub_list_node_free(iter);
-	}
-	lub_list_free(cmds);
+	lub_list_free_all(cmds);
 
 	/* Stop XML engine */
 	clish_xmldoc_stop();

+ 1 - 1
clish/nspace.h

@@ -23,7 +23,7 @@ typedef enum {
 
 clish_nspace_t *clish_nspace_new(const char *view_name);
 
-void clish_nspace_delete(clish_nspace_t * instance);
+void clish_nspace_delete(void *instance);
 const clish_command_t *clish_nspace_find_next_completion(clish_nspace_t *
 	instance, const char *iter_cmd, const char *line,
 	clish_nspace_visibility_e field);

+ 2 - 1
clish/nspace/nspace.c

@@ -140,8 +140,9 @@ clish_nspace_t *clish_nspace_new(const char *view_name)
 }
 
 /*--------------------------------------------------------- */
-void clish_nspace_delete(clish_nspace_t *this)
+void clish_nspace_delete(void *data)
 {
+	clish_nspace_t *this = (clish_nspace_t *)data;
 	clish_nspace_fini(this);
 	free(this);
 }

+ 4 - 4
clish/plugin.h

@@ -71,7 +71,7 @@ extern clish_plugin_builtin_list_t clish_plugin_builtin_list[];
 
 int clish_sym_compare(const void *first, const void *second);
 clish_sym_t *clish_sym_new(const char *name, void *func, int type);
-void clish_sym_free(clish_sym_t *instance);
+void clish_sym_free(void *instance);
 int clish_sym_clone(clish_sym_t *dst, clish_sym_t *src);
 
 _CLISH_SET(sym, const void *, func);
@@ -89,9 +89,9 @@ _CLISH_GET(sym, clish_sym_api_e, api);
 
 /* Plugin */
 
-clish_plugin_t *clish_plugin_new(const char *name);
-void clish_plugin_free(clish_plugin_t *instance, void *userdata);
-int clish_plugin_load(clish_plugin_t *instance, void *userdata);
+clish_plugin_t *clish_plugin_new(const char *name, void *userdata);
+void clish_plugin_free(clish_plugin_t *instance);
+int clish_plugin_load(clish_plugin_t *instance);
 clish_sym_t *clish_plugin_get_sym(clish_plugin_t *instance,
 	const char *name, int type);
 clish_sym_t *clish_plugin_add_generic(clish_plugin_t *instance,

+ 9 - 16
clish/plugin/plugin.c

@@ -19,7 +19,7 @@
 #endif
 
 /*--------------------------------------------------------- */
-clish_plugin_t *clish_plugin_new(const char *name)
+clish_plugin_t *clish_plugin_new(const char *name, void *userdata)
 {
 	clish_plugin_t *this;
 
@@ -32,27 +32,27 @@ clish_plugin_t *clish_plugin_new(const char *name)
 	this->builtin_flag = BOOL_FALSE; /* The plugin is shared object by default */
 	this->dlhan = NULL;
 	/* Initialise the list of symbols */
-	this->syms = lub_list_new(clish_sym_compare);
+	this->syms = lub_list_new(clish_sym_compare, clish_sym_free);
 	/* Constructor and destructor */
 	this->init = NULL;
 	this->fini = NULL;
 	/* Flags */
 	this->rtld_global = BOOL_FALSE; /* The dlopen() use RTLD_LOCAL by default */
+	/* Userdata */
+	this->userdata = userdata;
 
 	return this;
 }
 
 /*--------------------------------------------------------- */
-void clish_plugin_free(clish_plugin_t *this, void *userdata)
+void clish_plugin_free(clish_plugin_t *this)
 {
-	lub_list_node_t *iter;
-
 	if (!this)
 		return;
 
 	/* Execute destructor */
 	if (this->fini)
-		this->fini(userdata, this);
+		this->fini(this->userdata, this);
 
 	lub_string_free(this->name);
 	lub_string_free(this->alias);
@@ -60,14 +60,7 @@ void clish_plugin_free(clish_plugin_t *this, void *userdata)
 	lub_string_free(this->conf);
 
 	/* Free symbol list */
-	while ((iter = lub_list__get_head(this->syms))) {
-		/* Remove the symbol from the list */
-		lub_list_del(this->syms, iter);
-		/* Free the instance */
-		clish_sym_free((clish_sym_t *)lub_list_node__get_data(iter));
-		lub_list_node_free(iter);
-	}
-	lub_list_free(this->syms);
+	lub_list_free_all(this->syms);
 #ifdef HAVE_DLFCN_H
 	if (this->dlhan)
 		dlclose(this->dlhan);
@@ -227,7 +220,7 @@ static int clish_plugin_load_shared(clish_plugin_t *this)
 }
 
 /*--------------------------------------------------------- */
-int clish_plugin_load(clish_plugin_t *this, void *userdata)
+int clish_plugin_load(clish_plugin_t *this)
 {
 	int res;
 
@@ -246,7 +239,7 @@ int clish_plugin_load(clish_plugin_t *this, void *userdata)
 		return -1;
 	}
 	/* Execute init function */
-	if ((res = this->init(userdata, this)))
+	if ((res = this->init(this->userdata, this)))
 		fprintf(stderr, "Error: Plugin %s init retcode: %d\n",
 			this->name, res);
 

+ 1 - 0
clish/plugin/private.h

@@ -29,4 +29,5 @@ struct clish_plugin_s {
 	clish_plugin_init_t *init; /* Init function (constructor) != NULL */
 	clish_plugin_fini_t *fini; /* Fini function (destructor) */
 	bool_t rtld_global; /* RTLD_GLOBAL flag for dlopen() */
+	void *userdata; /* Arbitrary userdata to pass to ini and fini functions */
 };

+ 3 - 2
clish/plugin/sym.c

@@ -43,9 +43,10 @@ clish_sym_t *clish_sym_new(const char *name, void *func, int type)
 }
 
 /*--------------------------------------------------------- */
-void clish_sym_free(clish_sym_t *this)
+void clish_sym_free(void *data)
 {
-	if (!this)
+	clish_sym_t *this = (clish_sym_t *)data;
+	if (!data)
 		return;
 	lub_string_free(this->name);
 	free(this);

+ 1 - 1
clish/ptype.h

@@ -57,7 +57,7 @@ clish_ptype_t *clish_ptype_new(const char *name, const char *text,
 	const char *pattern, clish_ptype_method_e method,
 	clish_ptype_preprocess_e preprocess);
 
-void clish_ptype_free(clish_ptype_t *instance);
+void clish_ptype_free(void *instance);
 /**
  * This is the validation method for the specified type.
  * \return

+ 2 - 1
clish/ptype/ptype.c

@@ -88,8 +88,9 @@ clish_ptype_t *clish_ptype_new(const char *name,
 }
 
 /*--------------------------------------------------------- */
-void clish_ptype_free(clish_ptype_t *this)
+void clish_ptype_free(void *data)
 {
+	clish_ptype_t *this = (clish_ptype_t *)data;
 	clish_ptype_fini(this);
 	free(this);
 }

+ 2 - 0
clish/shell.h

@@ -203,6 +203,8 @@ int clish_shell__restore_history(clish_shell_t *instance, const char *fname);
 void clish_shell__stifle_history(clish_shell_t *instance, unsigned int stifle);
 
 /* Plugin functions */
+clish_plugin_t * clish_shell_create_plugin(clish_shell_t *instance,
+	const char *name);
 clish_plugin_t * clish_shell_find_plugin(clish_shell_t *instance,
 	const char *name);
 clish_plugin_t * clish_shell_find_create_plugin(clish_shell_t *instance,

+ 1 - 1
clish/shell/private.h

@@ -46,7 +46,7 @@ struct clish_context_s {
 
 /* Shell structure */
 struct clish_shell_s {
-	lub_bintree_t view_tree; /* Tree of views */
+	lub_list_t *view_tree; /* VIEW list */
 	lub_list_t *ptype_tree; /* PTYPE list */
 	lub_bintree_t var_tree; /* Tree of global variables */
 

+ 1 - 1
clish/shell/shell_execute.c

@@ -229,7 +229,7 @@ static int clish_shell_exec_oaction(clish_hook_oaction_fn_t func,
 
 		close(pipe1[1]);
 		close(pipe2[0]);
-		l = lub_list_new(NULL);
+		l = lub_list_new(NULL, NULL);
 
 		/* Read the result of script execution */
 		while (1) {

+ 12 - 37
clish/shell/shell_new.c

@@ -23,13 +23,11 @@ static void clish_shell_init(clish_shell_t * this,
 	int i;
 	char template[PATH_MAX];
 
-	/* initialise the tree of views */
-	lub_bintree_init(&this->view_tree,
-		clish_view_bt_offset(),
-		clish_view_bt_compare, clish_view_bt_getkey);
+	/* Initialise VIEW list */
+	this->view_tree = lub_list_new(clish_view_compare, clish_view_delete);
 
 	/* Init PTYPE list */
-	this->ptype_tree = lub_list_new(clish_ptype_compare);
+	this->ptype_tree = lub_list_new(clish_ptype_compare, clish_ptype_free);
 
 	/* initialise the tree of vars */
 	lub_bintree_init(&this->var_tree,
@@ -37,14 +35,13 @@ static void clish_shell_init(clish_shell_t * this,
 		clish_var_bt_compare, clish_var_bt_getkey);
 
 	/* Initialize plugin list */
-	this->plugins = lub_list_new(NULL);
+	this->plugins = lub_list_new(NULL, NULL);
 
 	/* Initialise the list of unresolved (yet) symbols */
-	this->syms = lub_list_new(clish_sym_compare);
+	this->syms = lub_list_new(clish_sym_compare, clish_sym_free);
 
 	/* Create userdata storage */
-	this->udata = lub_list_new(clish_udata_compare);
-	assert(this->udata);
+	this->udata = lub_list_new(clish_udata_compare, clish_udata_delete);
 
 	/* Hooks */
 	for (i = 0; i < CLISH_SYM_TYPE_MAX; i++) {
@@ -102,7 +99,7 @@ static void clish_shell_fini(clish_shell_t *this)
 {
 	clish_view_t *view;
 	clish_var_t *var;
-	unsigned i;
+	unsigned int i;
 	lub_list_node_t *iter;
 
 	/* Free all loaded plugins */
@@ -116,19 +113,11 @@ static void clish_shell_fini(clish_shell_t *this)
 	}
 	lub_list_free(this->plugins);
 
-	/* delete each VIEW held  */
-	while ((view = lub_bintree_findfirst(&this->view_tree))) {
-		lub_bintree_remove(&this->view_tree, view);
-		clish_view_delete(view);
-	}
+	/* Delete each VIEW  */
+	lub_list_free_all(this->view_tree);
 
 	/* Delete each PTYPE  */
-	while ((iter = lub_list__get_head(this->ptype_tree))) {
-		lub_list_del(this->ptype_tree, iter);
-		clish_ptype_free((clish_ptype_t *)lub_list_node__get_data(iter));
-		lub_list_node_free(iter);
-	}
-	lub_list_free(this->ptype_tree);
+	lub_list_free_all(this->ptype_tree);
 
 	/* delete each VAR held  */
 	while ((var = lub_bintree_findfirst(&this->var_tree))) {
@@ -144,24 +133,10 @@ static void clish_shell_fini(clish_shell_t *this)
 	}
 
 	/* Free symbol list */
-	while ((iter = lub_list__get_head(this->syms))) {
-		/* Remove the symbol from the list */
-		lub_list_del(this->syms, iter);
-		/* Free the instance */
-		clish_sym_free((clish_sym_t *)lub_list_node__get_data(iter));
-		lub_list_node_free(iter);
-	}
-	lub_list_free(this->syms);
+	lub_list_free_all(this->syms);
 
 	/* Free user data storage */
-	while ((iter = lub_list__get_head(this->udata))) {
-		/* Remove the symbol from the list */
-		lub_list_del(this->udata, iter);
-		/* Free the instance */
-		clish_udata_free((clish_udata_t *)lub_list_node__get_data(iter));
-		lub_list_node_free(iter);
-	}
-	lub_list_free(this->udata);
+	lub_list_free_all(this->udata);
 
 	/* free the textual details */
 	lub_string_free(this->overview);

+ 10 - 5
clish/shell/shell_plugin.c

@@ -34,7 +34,7 @@ clish_plugin_t * clish_shell_find_plugin(clish_shell_t *this, const char *name)
 }
 
 /*----------------------------------------------------------------------- */
-clish_plugin_t * clish_shell_find_create_plugin(clish_shell_t *this,
+clish_plugin_t * clish_shell_create_plugin(clish_shell_t *this,
 	const char *name)
 {
 	clish_plugin_t *plugin;
@@ -43,15 +43,20 @@ clish_plugin_t * clish_shell_find_create_plugin(clish_shell_t *this,
 	if (!name || !name[0])
 		return NULL;
 
-	plugin = clish_shell_find_plugin(this, name);
-	if (plugin)
-		return plugin;
-	plugin = clish_plugin_new(name);
+	plugin = clish_plugin_new(name, this);
 	lub_list_add(this->plugins, plugin);
 
 	return plugin;
 }
 
+/*----------------------------------------------------------------------- */
+clish_plugin_t * clish_shell_find_create_plugin(clish_shell_t *this,
+	const char *name)
+{
+	clish_plugin_t *plugin = clish_shell_find_plugin(this, name);
+	return (plugin ? plugin : clish_shell_create_plugin(this, name);
+}
+
 /*----------------------------------------------------------------------- */
 /* For all plugins:
  *  * dlopen(plugin)

+ 1 - 2
clish/shell/shell_xml.c

@@ -1235,8 +1235,7 @@ static int process_plugin(clish_shell_t *shell, clish_xmlnode_t *element,
 			CLISH_XML_ERROR_STR"PLUGIN %s duplication.\n", name);
 		goto error;
 	}
-	plugin = clish_plugin_new(name);
-	lub_list_add(shell->plugins, plugin);
+	plugin = clish_shell_create_plugin(shell, name);
 
 	if (alias && *alias)
 		clish_plugin__set_alias(plugin, alias);

+ 1 - 0
clish/udata.h

@@ -18,6 +18,7 @@ typedef struct clish_udata_s clish_udata_t;
 int clish_udata_compare(const void *first, const void *second);
 clish_udata_t *clish_udata_new(const char *name, void *data);
 void *clish_udata_free(clish_udata_t *instance);
+void clish_udata_delete(void *data);
 
 _CLISH_SET(udata, void *, data);
 _CLISH_GET(udata, void *, data);

+ 7 - 0
clish/udata/udata.c

@@ -52,6 +52,13 @@ void *clish_udata_free(clish_udata_t *this)
 	return data;
 }
 
+/*--------------------------------------------------------- */
+void clish_udata_delete(void *data)
+{
+	clish_udata_t *this = (clish_udata_t *)data;
+	clish_udata_free(this);
+}
+
 CLISH_SET(udata, void *, data);
 CLISH_GET(udata, void *, data);
 CLISH_GET_STR(udata, name);

+ 1 - 3
clish/view.h

@@ -30,9 +30,7 @@ typedef enum {
 #include "clish/var.h"
 
 clish_view_t *clish_view_new(const char *name, const char *prompt);
-int clish_view_bt_compare(const void *clientnode, const void *clientkey);
-void clish_view_bt_getkey(const void *clientnode, lub_bintree_key_t * key);
-size_t clish_view_bt_offset(void);
+int clish_view_compare(const void *clientnode, const void *clientkey);
 void clish_view_delete(clish_view_t * instance);
 clish_command_t *clish_view_new_command(clish_view_t * instance,
 	const char *name, const char *text);

+ 0 - 4
clish/view/private.h

@@ -6,12 +6,8 @@
 #include "lub/list.h"
 #include "clish/hotkey.h"
 
-/*---------------------------------------------------------
- * PRIVATE TYPES
- *--------------------------------------------------------- */
 struct clish_view_s {
 	lub_bintree_t tree;
-	lub_bintree_node_t bt_node;
 	char *name;
 	char *prompt;
 	char *access;

+ 5 - 30
clish/view/view.c

@@ -15,7 +15,7 @@
 #include <stdio.h>
 
 /*-------------------------------------------------------- */
-int clish_view_bt_compare(const void *clientnode, const void *clientkey)
+int clish_view_compare(const void *clientnode, const void *clientkey)
 {
 	const clish_view_t *this = clientnode;
 	const char *key = clientkey;
@@ -23,15 +23,6 @@ int clish_view_bt_compare(const void *clientnode, const void *clientkey)
 	return strcmp(this->name, key);
 }
 
-/*-------------------------------------------------------- */
-void clish_view_bt_getkey(const void *clientnode, lub_bintree_key_t * key)
-{
-	const clish_view_t *this = clientnode;
-
-	/* fill out the opaque key */
-	strcpy((char *)key, this->name);
-}
-
 /*-------------------------------------------------------- */
 static void clish_view_init(clish_view_t * this, const char *name, const char *prompt)
 {
@@ -42,9 +33,6 @@ static void clish_view_init(clish_view_t * this, const char *name, const char *p
 	this->restore = CLISH_RESTORE_NONE;
 	this->access = NULL;
 
-	/* Be a good binary tree citizen */
-	lub_bintree_node_init(&this->bt_node);
-
 	/* initialise the tree of commands for this view */
 	lub_bintree_init(&this->tree,
 		clish_command_bt_offset(),
@@ -54,7 +42,7 @@ static void clish_view_init(clish_view_t * this, const char *name, const char *p
 	 * It's important to add new items to the
 	 * tail of list.
 	 */
-	this->nspaces = lub_list_new(NULL);
+	this->nspaces = lub_list_new(NULL, clish_nspace_delete);
 
 	/* set up the defaults */
 	clish_view__set_prompt(this, prompt);
@@ -79,15 +67,7 @@ static void clish_view_fini(clish_view_t * this)
 	}
 
 	/* Free namespaces list */
-	while ((iter = lub_list__get_head(this->nspaces))) {
-		/* Remove the nspace from the list */
-		lub_list_del(this->nspaces, iter);
-		nspace = (clish_nspace_t *)lub_list_node__get_data(iter);
-		lub_list_node_free(iter);
-		/* Free the instance */
-		clish_nspace_delete(nspace);
-	}
-	lub_list_free(this->nspaces);
+	lub_list_free_all(this->nspaces);
 
 	/* Free hotkey structures */
 	clish_hotkeyv_delete(this->hotkeys);
@@ -98,12 +78,6 @@ static void clish_view_fini(clish_view_t * this)
 	lub_string_free(this->access);
 }
 
-/*-------------------------------------------------------- */
-size_t clish_view_bt_offset(void)
-{
-	return offsetof(clish_view_t, bt_node);
-}
-
 /*--------------------------------------------------------- */
 clish_view_t *clish_view_new(const char *name, const char *prompt)
 {
@@ -115,8 +89,9 @@ clish_view_t *clish_view_new(const char *name, const char *prompt)
 }
 
 /*-------------------------------------------------------- */
-void clish_view_delete(clish_view_t * this)
+void clish_view_delete(void *data)
 {
+	clish_view_t this = (clish_view_t *)data;
 	clish_view_fini(this);
 	free(this);
 }

+ 1 - 24
konf/tree.h

@@ -1,16 +1,6 @@
 /*
  * conf.h
  */
- /**
-\ingroup clish
-\defgroup clish_conf config
-@{
-
-\brief This class is a config in memory container.
-
-Use it to implement config in memory.
-
-*/
 #ifndef _konf_tree_h
 #define _konf_tree_h
 
@@ -25,18 +15,9 @@ typedef struct konf_tree_s konf_tree_t;
 #define KONF_ENTRY_DIRTY 0xfffe
 #define KONF_ENTRY_NEW 0xfffd
 
-/*=====================================
- * CONF INTERFACE
- *===================================== */
-/*-----------------
- * meta functions
- *----------------- */
 konf_tree_t *konf_tree_new(const char *line, unsigned short priority);
 
-/*-----------------
- * methods
- *----------------- */
-void konf_tree_delete(konf_tree_t * instance);
+void konf_tree_delete(void *instance);
 void konf_tree_fprintf(konf_tree_t * instance, FILE * stream,
 	const char *pattern, int top_depth, int depth,
 	bool_t seq, bool_t splitter, unsigned char prev_pri_hi);
@@ -50,9 +31,6 @@ int konf_tree_del_pattern(konf_tree_t * instance,
 	const char *pattern, unsigned short priority,
 	bool_t seq, unsigned short seq_num);
 
-/*-----------------
- * attributes
- *----------------- */
 unsigned short konf_tree__get_priority(const konf_tree_t * instance);
 unsigned char konf_tree__get_priority_hi(const konf_tree_t * instance);
 unsigned char konf_tree__get_priority_lo(const konf_tree_t * instance);
@@ -67,4 +45,3 @@ void konf_tree__set_depth(konf_tree_t * instance, int depth);
 int konf_tree__get_depth(const konf_tree_t * instance);
 
 #endif				/* _konf_tree_h */
-/** @} clish_conf */

+ 7 - 30
konf/tree/tree.c

@@ -16,9 +16,7 @@
 #include <sys/types.h>
 #include <regex.h>
 
-/*---------------------------------------------------------
- * PRIVATE META FUNCTIONS
- *--------------------------------------------------------- */
+/*--------------------------------------------------------- */
 static int konf_tree_compare(const void *first, const void *second)
 {
 	const konf_tree_t *f = (const konf_tree_t *)first;
@@ -37,9 +35,7 @@ static int konf_tree_compare(const void *first, const void *second)
 	return strcmp(f->line, s->line);
 }
 
-/*---------------------------------------------------------
- * PRIVATE METHODS
- *--------------------------------------------------------- */
+/*--------------------------------------------------------- */
 static void konf_tree_init(konf_tree_t * this, const char *line,
 	unsigned short priority)
 {
@@ -52,34 +48,16 @@ static void konf_tree_init(konf_tree_t * this, const char *line,
 	this->depth = -1;
 
 	/* initialise the list of commands for this conf */
-	this->list = lub_list_new(konf_tree_compare);
+	this->list = lub_list_new(konf_tree_compare, konf_tree_delete);
 }
 
 /*--------------------------------------------------------- */
 static void konf_tree_fini(konf_tree_t * this)
 {
-	lub_list_node_t *iter;
-
-	/* delete each conf held by this conf */
-	
-	while ((iter = lub_list__get_head(this->list))) {
-		/* remove the conf from the tree */
-		lub_list_del(this->list, iter);
-		/* release the instance */
-		konf_tree_delete((konf_tree_t *)lub_list_node__get_data(iter));
-		lub_list_node_free(iter);
-	}
-	lub_list_free(this->list);
-
-	/* free our memory */
+	lub_list_free_all(this->list);
 	free(this->line);
-	this->line = NULL;
 }
 
-/*---------------------------------------------------------
- * PUBLIC META FUNCTIONS
- *--------------------------------------------------------- */
-
 /*--------------------------------------------------------- */
 konf_tree_t *konf_tree_new(const char *line, unsigned short priority)
 {
@@ -91,11 +69,10 @@ konf_tree_t *konf_tree_new(const char *line, unsigned short priority)
 	return this;
 }
 
-/*---------------------------------------------------------
- * PUBLIC METHODS
- *--------------------------------------------------------- */
-void konf_tree_delete(konf_tree_t * this)
+/*--------------------------------------------------------- */
+void konf_tree_delete(void *data)
 {
+	konf_tree_t *this = (konf_tree_t *)data;
 	konf_tree_fini(this);
 	free(this);
 }

+ 1 - 1
lub/ini.h

@@ -19,7 +19,7 @@ int lub_pair_compare(const void *first, const void *second);
 void lub_pair_init(lub_pair_t *instance, const char *name, const char *value);
 lub_pair_t *lub_pair_new(const char *name, const char *value);
 void lub_pair_fini(lub_pair_t *instance);
-void lub_pair_free(lub_pair_t *instance);
+void lub_pair_free(void *instance);
 const char *lub_pair__get_name(const lub_pair_t *instance);
 void lub_pair__set_name(lub_pair_t *instance, const char *name);
 const char *lub_pair__get_value(const lub_pair_t *instance);

+ 2 - 10
lub/ini/ini.c

@@ -16,7 +16,7 @@ void lub_ini_init(lub_ini_t *this)
 {
 	assert(this);
 	memset(this, 0, sizeof(*this));
-	this->list = lub_list_new(lub_pair_compare);
+	this->list = lub_list_new(lub_pair_compare, lub_pair_free);
 }
 
 /*--------------------------------------------------------- */
@@ -34,15 +34,7 @@ lub_ini_t *lub_ini_new(void)
 /*--------------------------------------------------------- */
 void lub_ini_fini(lub_ini_t *this)
 {
-	lub_list_node_t *iter;
-
-	assert(this);
-	while ((iter = lub_list__get_head(this->list))) {
-		lub_list_del(this->list, iter);
-		lub_pair_free((lub_pair_t *)lub_list_node__get_data(iter));
-		lub_list_node_free(iter);
-	}
-	lub_list_free(this->list);
+	lub_list_free_all(this->list);
 }
 
 /*--------------------------------------------------------- */

+ 3 - 2
lub/ini/pair.c

@@ -48,9 +48,10 @@ void lub_pair_fini(lub_pair_t *this)
 }
 
 /*--------------------------------------------------------- */
-void lub_pair_free(lub_pair_t *this)
+void lub_pair_free(void *data)
 {
-	assert(this);
+	assert(data);
+	lub_pair_t *this = (lub_pair_t *)data;
 	lub_pair_fini(this);
 	free(this);
 }

+ 4 - 1
lub/list.h

@@ -6,6 +6,7 @@
 
 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 struct lub_list_s lub_list_t;
 typedef struct lub_list_node_s lub_list_iterator_t;
 
@@ -18,8 +19,10 @@ 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_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);

+ 27 - 5
lub/list/list.c

@@ -5,23 +5,26 @@
 #include "private.h"
 
 /*--------------------------------------------------------- */
-static inline void lub_list_init(lub_list_t * this,
-	lub_list_compare_fn compareFn)
+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_t *lub_list_new(lub_list_compare_fn compareFn,
+	lub_list_free_fn freeFn)
 {
 	lub_list_t *this;
 
 	this = malloc(sizeof(*this));
 	assert(this);
-	lub_list_init(this, compareFn);
+	lub_list_init(this, compareFn, freeFn);
 
 	return this;
 }
@@ -32,6 +35,25 @@ inline void lub_list_free(lub_list_t *this)
 	free(this);
 }
 
+/*--------------------------------------------------------- */
+/* 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.
+ */
+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);
+}
+
 /*--------------------------------------------------------- */
 inline lub_list_node_t *lub_list__get_head(lub_list_t *this)
 {
@@ -45,7 +67,7 @@ inline lub_list_node_t *lub_list__get_tail(lub_list_t *this)
 }
 
 /*--------------------------------------------------------- */
-static inline void lub_list_node_init(lub_list_node_t *this,
+static void lub_list_node_init(lub_list_node_t *this,
 	void *data)
 {
 	this->prev = this->next = NULL;

+ 2 - 1
lub/list/private.h

@@ -9,6 +9,7 @@ struct lub_list_node_s {
 struct lub_list_s {
 	lub_list_node_t *head;
 	lub_list_node_t *tail;
-	lub_list_compare_fn *compareFn;
+	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;
 };