Browse Source

Engine to parse INI-like strings

Serj Kalichev 11 years ago
parent
commit
882e889219

+ 2 - 2
clish/shell/shell_command.c

@@ -79,9 +79,9 @@ void clish_shell_param_generator(clish_shell_t *this, lub_argv_t *matches,
 	const char *name = clish_command__get_name(cmd);
 	char *text = lub_string_dup(&line[offset]);
 	clish_ptype_t *ptype;
-	unsigned idx = lub_argv_wordcount(name);
+	unsigned idx = lub_string_wordcount(name);
 	/* get the index of the current parameter */
-	unsigned index = lub_argv_wordcount(line) - idx;
+	unsigned index = lub_string_wordcount(line) - idx;
 	clish_context_t context;
 
 	if ((0 != index) || (offset && line[offset - 1] == ' ')) {

+ 2 - 2
clish/shell/shell_help.c

@@ -42,8 +42,8 @@ static int available_params(clish_shell_t *this,
 	clish_help_t *help, const clish_command_t *cmd,
 	const char *line, size_t *max_width)
 {
-	unsigned index = lub_argv_wordcount(line);
-	unsigned idx = lub_argv_wordcount(clish_command__get_name(cmd));
+	unsigned index = lub_string_wordcount(line);
+	unsigned idx = lub_string_wordcount(clish_command__get_name(cmd));
 	lub_argv_t *argv;
 	clish_pargv_t *completion, *pargv;
 	unsigned i;

+ 1 - 1
clish/shell/shell_parse.c

@@ -31,7 +31,7 @@ clish_pargv_status_t clish_shell_parse(
 	clish_context__set_cmd(&context, cmd);
 	clish_context__set_pargv(&context, *pargv);
 
-	idx = lub_argv_wordcount(clish_command__get_name(cmd));
+	idx = lub_string_wordcount(clish_command__get_name(cmd));
 	argv = lub_argv_new(line, 0);
 	result = clish_shell_parse_pargv(*pargv, cmd, &context,
 		clish_command__get_paramv(cmd),

+ 2 - 2
clish/shell/shell_var.c

@@ -98,8 +98,8 @@ static char *find_context_var(const char *name, clish_context_t *this)
 	} else if (lub_string_nocasestr(name, "_prefix") == name) {
 		int idx = 0;
 		int pnum = 0;
-		pnum = lub_argv_wordcount(clish_command__get_name(this->cmd)) -
-			lub_argv_wordcount(clish_command__get_name(
+		pnum = lub_string_wordcount(clish_command__get_name(this->cmd)) -
+			lub_string_wordcount(clish_command__get_name(
 			clish_command__get_cmd(this->cmd)));
 		idx = atoi(name + strlen("_prefix"));
 		if (idx < pnum) {

+ 1 - 1
clish/view/view.c

@@ -256,7 +256,7 @@ static const clish_command_t *find_next_completion(clish_view_t * this,
 		/* Make command link from command alias */
 		cmd = clish_command_alias_to_link(cmd);
 		name = clish_command__get_name(cmd);
-		if (words == lub_argv_wordcount(name)) {
+		if (words == lub_string_wordcount(name)) {
 			/* only bother with commands of which this line is a prefix */
 			/* this is a completion */
 			if (lub_string_nocasestr(name, line) == name)

+ 21 - 3
examples/explugin/anplug.c

@@ -1,6 +1,8 @@
 #include <stdlib.h>
 #include <stdio.h>
-#include <clish/plugin.h>
+
+#include "clish/plugin.h"
+#include "lub/ini.h"
 
 CLISH_PLUGIN_SYM(anplug_fn)
 {
@@ -11,6 +13,9 @@ CLISH_PLUGIN_SYM(anplug_fn)
 CLISH_PLUGIN_INIT
 {
 	char *conf;
+	lub_ini_t *ini;
+	lub_ini_node_t *iter;
+	lub_pair_t *pair;
 
 	printf("anplug: INIT shell = %p\n", clish_shell);
 	/* Set a name of plugin to use in sym@plugin */
@@ -19,8 +24,21 @@ CLISH_PLUGIN_INIT
 	clish_plugin_add_sym(plugin, anplug_fn, "an_fn");
 	/* Show plugin config from <PLUGIN>...</PLUGIN> */
 	conf = clish_plugin__get_conf(plugin);
-	if (conf)
-		printf("%s", conf);
+	ini = lub_ini_new();
+	lub_ini_parse_str(ini, conf);
+	/* Iterate INI elements */
+	for(iter = lub_ini__get_head(ini);
+		iter; iter = lub_ini__get_next(iter)) {
+		pair = lub_ini__iter_data(iter);
+		printf("anplug iter: [%s] = [%s]\n",
+			lub_pair__get_name(pair),
+			lub_pair__get_value(pair));
+	}
+
+	/* Get specified config element */
+	printf("anplug conf: vvv = %s\n", lub_ini_find(ini, "vvv"));
+
+	lub_ini_free(ini);
 
 	return 0;
 }

+ 0 - 15
lub/argv.h

@@ -36,21 +36,6 @@ typedef struct lub_argv_s lub_argv_t;
 /*=====================================
  * ARGV INTERFACE
  *===================================== */
-/**
- * \pre
- * - none
- *
- * \return
- * The number of space separated words in the specified string.
- *
- * \post
- * - none
- */
-unsigned lub_argv_wordcount(
-	/**
-         * The string to analyse
-         */
-	const char *line);
 /**
  *  This operation is used to construct an instance of this class. The client
  * species a string and an offset within that string, from which to start

+ 3 - 3
lub/argv/argv_new.c

@@ -21,7 +21,7 @@ static void lub_argv_init(lub_argv_t * this, const char *line, size_t offset)
 	if (!line)
 		return;
 	/* first of all count the words in the line */
-	this->argc = lub_argv_wordcount(line);
+	this->argc = lub_string_wordcount(line);
 	if (0 == this->argc)
 		return;
 	/* allocate space to hold the vector */
@@ -29,9 +29,9 @@ static void lub_argv_init(lub_argv_t * this, const char *line, size_t offset)
 	assert(arg);
 
 	/* then fill out the array with the words */
-	for (word = lub_argv_nextword(line, &len, &offset, &quoted);
+	for (word = lub_string_nextword(line, &len, &offset, &quoted);
 		*word || quoted;
-		word = lub_argv_nextword(word + len, &len, &offset, &quoted)) {
+		word = lub_string_nextword(word + len, &len, &offset, &quoted)) {
 		(*arg).arg = lub_string_ndecode(word, len);
 		(*arg).offset = offset;
 		(*arg).quoted = quoted ? BOOL_TRUE : BOOL_FALSE;

+ 8 - 9
lub/argv/module.am

@@ -1,12 +1,11 @@
-liblub_la_SOURCES +=                            \
-                    lub/argv/argv__get_arg.c	\
-                    lub/argv/argv__get_argv.c	\
-                    lub/argv/argv__get_count.c	\
-                    lub/argv/argv__get_offset.c	\
-                    lub/argv/argv__get_quoted.c	\
-                    lub/argv/argv_new.c		\
-                    lub/argv/argv_nextword.c	\
-                    lub/argv/private.h
+liblub_la_SOURCES += \
+	lub/argv/argv__get_arg.c \
+	lub/argv/argv__get_argv.c \
+	lub/argv/argv__get_count.c \
+	lub/argv/argv__get_offset.c \
+	lub/argv/argv__get_quoted.c \
+	lub/argv/argv_new.c \
+	lub/argv/private.h
 
 
 

+ 0 - 5
lub/argv/private.h

@@ -17,8 +17,3 @@ struct lub_argv_s {
 	unsigned argc;
 	lub_arg_t *argv;
 };
-/*-------------------------------------
- * PRIVATE META FUNCTIONS
- *------------------------------------- */
-const char *lub_argv_nextword(const char *string,
-	size_t * len, size_t * offset, size_t * quoted);

+ 44 - 0
lub/ini.h

@@ -0,0 +1,44 @@
+/*
+ * ini.h
+ */
+
+#ifndef _lub_ini_h
+#define _lub_ini_h
+
+#include "lub/c_decl.h"
+#include "lub/list.h"
+
+typedef struct lub_pair_s lub_pair_t;
+typedef struct lub_ini_s lub_ini_t;
+typedef lub_list_node_t lub_ini_node_t;
+
+_BEGIN_C_DECL
+
+/* Pair */
+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);
+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);
+void lub_pair__set_value(lub_pair_t *instance, const char *value);
+
+/* Ini */
+void lub_ini_init(lub_ini_t *instance);
+lub_ini_t *lub_ini_new(void);
+void lub_ini_fini(lub_ini_t *instance);
+void lub_ini_free(lub_ini_t *instance);
+lub_pair_t *lub_ini_find_pair(const lub_ini_t *instance, const char *name);
+const char *lub_ini_find(const lub_ini_t *instance, const char *name);
+void lub_ini_add(lub_ini_t *instance, lub_pair_t *pair);
+lub_ini_node_t *lub_ini__get_head(lub_ini_t *instance);
+lub_ini_node_t *lub_ini__get_tail(lub_ini_t *instance);
+lub_ini_node_t *lub_ini__get_next(lub_ini_node_t *node);
+lub_ini_node_t *lub_ini__get_prev(lub_ini_node_t *node);
+lub_pair_t *lub_ini__iter_data(lub_ini_node_t *node);
+
+_END_C_DECL
+
+#endif				/* _lub_ini_h */

+ 181 - 0
lub/ini/ini.c

@@ -0,0 +1,181 @@
+/*
+ * ini.c
+ */
+
+#include "private.h"
+#include "lub/string.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+
+/*--------------------------------------------------------- */
+void lub_ini_init(lub_ini_t *this)
+{
+	assert(this);
+	memset(this, 0, sizeof(*this));
+	this->list = lub_list_new(lub_pair_compare);
+}
+
+/*--------------------------------------------------------- */
+lub_ini_t *lub_ini_new(void)
+{
+	lub_ini_t *this;
+
+	this = malloc(sizeof(*this));
+	if (this)
+		lub_ini_init(this);
+
+	return this;
+}
+
+/*--------------------------------------------------------- */
+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);
+}
+
+/*--------------------------------------------------------- */
+void lub_ini_free(lub_ini_t *this)
+{
+	assert(this);
+	lub_ini_fini(this);
+	free(this);
+}
+
+/*--------------------------------------------------------- */
+void lub_ini_add(lub_ini_t *this, lub_pair_t *pair)
+{
+	assert(this);
+	lub_list_add(this->list, pair);
+}
+
+/*--------------------------------------------------------- */
+/* Find pair by name */
+lub_pair_t *lub_ini_find_pair(const lub_ini_t *this, const char *name)
+{
+	lub_list_node_t *iter;
+	lub_pair_t *pair;
+
+	if (!this || !name)
+		return NULL;
+	/* Iterate elements */
+	for(iter = lub_list__get_head(this->list);
+		iter; iter = lub_list_node__get_next(iter)) {
+		int res;
+		pair = (lub_pair_t *)lub_list_node__get_data(iter);
+		res = strcmp(lub_pair__get_name(pair), name);
+		if (!res)
+			return pair;
+		if (res > 0) /* No chance to find name */
+			break;
+	}
+
+	return NULL;
+}
+
+/*--------------------------------------------------------- */
+/* Find pair by name */
+const char *lub_ini_find(const lub_ini_t *this, const char *name)
+{
+	lub_pair_t *pair = lub_ini_find_pair(this, name);
+
+	if (!pair)
+		return NULL;
+	return lub_pair__get_value(pair);
+}
+
+/*--------------------------------------------------------- */
+int lub_ini_parse_str(lub_ini_t *this, const char *ini)
+{
+	char *buffer;
+	char *saveptr;
+	char *line;
+
+	buffer = lub_string_dup(ini);
+	/* Now loop though each line */
+	for (line = strtok_r(buffer, "\n", &saveptr);
+		line; line = strtok_r(NULL, "\n", &saveptr)) {
+
+		char *str, *name, *value, *savestr, *ns = line;
+		const char *begin;
+		size_t len, offset, quoted;
+		char *rname, *rvalue;
+		lub_pair_t *pair;
+
+		if (!*ns) /* Empty */
+			continue;
+		while (*ns && isspace(*ns))
+			ns++;
+		if ('#' == *ns) /* Comment */
+			continue;
+		if ('=' == *ns) /* Broken string */
+			continue;
+		str = lub_string_dup(ns);
+		name = strtok_r(str, "=", &savestr);
+		if (!name) {
+			lub_string_free(str);
+			continue;
+		}
+		value = strtok_r(NULL, "=", &savestr);
+		begin = lub_string_nextword(name, &len, &offset, &quoted);
+		rname = lub_string_dupn(begin, len);
+		begin = lub_string_nextword(value, &len, &offset, &quoted);
+		rvalue = lub_string_dupn(begin, len);
+		pair = lub_pair_new(rname, rvalue);
+		lub_ini_add(this, pair);
+		lub_string_free(rname);
+		lub_string_free(rvalue);
+		lub_string_free(str);
+	}
+	lub_string_free(buffer);
+
+	return 0;
+}
+
+/*--------------------------------------------------------- */
+
+lub_ini_node_t *lub_ini__get_head(lub_ini_t *this)
+{
+	return lub_list__get_head(this->list);
+}
+
+/*--------------------------------------------------------- */
+
+lub_ini_node_t *lub_ini__get_tail(lub_ini_t *this)
+{
+	return lub_list__get_tail(this->list);
+}
+
+/*--------------------------------------------------------- */
+
+lub_ini_node_t *lub_ini__get_next(lub_ini_node_t *node)
+{
+	return lub_list_node__get_next(node);
+}
+
+/*--------------------------------------------------------- */
+
+lub_ini_node_t *lub_ini__get_prev(lub_ini_node_t *node)
+{
+	return lub_list_node__get_next(node);
+}
+
+/*--------------------------------------------------------- */
+
+lub_pair_t *lub_ini__iter_data(lub_ini_node_t *node)
+{
+	return (lub_pair_t *)lub_list_node__get_data(node);
+}
+
+/*--------------------------------------------------------- */

+ 6 - 0
lub/ini/module.am

@@ -0,0 +1,6 @@
+liblub_la_SOURCES += \
+	lub/ini/pair.c \
+	lub/ini/ini.c
+
+
+

+ 88 - 0
lub/ini/pair.c

@@ -0,0 +1,88 @@
+/*
+ * pair.c
+ */
+
+#include "private.h"
+#include "lub/string.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+/*--------------------------------------------------------- */
+int lub_pair_compare(const void *first, const void *second)
+{
+	const lub_pair_t *f = (const lub_pair_t *)first;
+	const lub_pair_t *s = (const lub_pair_t *)second;
+
+	return strcmp(f->name, s->name);
+}
+
+/*--------------------------------------------------------- */
+void lub_pair_init(lub_pair_t *this, const char *name, const char *value)
+{
+	assert(this);
+	memset(this, 0, sizeof(*this));
+	this->name = lub_string_dup(name);
+	this->value = lub_string_dup(value);
+}
+
+/*--------------------------------------------------------- */
+lub_pair_t *lub_pair_new(const char *name, const char *value)
+{
+	lub_pair_t *this;
+
+	this = malloc(sizeof(*this));
+	if (this)
+		lub_pair_init(this, name, value);
+
+	return this;
+}
+
+/*--------------------------------------------------------- */
+void lub_pair_fini(lub_pair_t *this)
+{
+	assert(this);
+	lub_string_free(this->name);
+	lub_string_free(this->value);
+}
+
+/*--------------------------------------------------------- */
+void lub_pair_free(lub_pair_t *this)
+{
+	assert(this);
+	lub_pair_fini(this);
+	free(this);
+}
+
+/*--------------------------------------------------------- */
+const char *lub_pair__get_name(const lub_pair_t *this)
+{
+	assert(this);
+	return this->name;
+}
+
+/*--------------------------------------------------------- */
+void lub_pair__set_name(lub_pair_t *this, const char *name)
+{
+	assert(this);
+	lub_string_free(this->name);
+	this->name = lub_string_dup(name);
+}
+
+/*--------------------------------------------------------- */
+const char *lub_pair__get_value(const lub_pair_t *this)
+{
+	assert(this);
+	return this->value;
+}
+
+/*--------------------------------------------------------- */
+void lub_pair__set_value(lub_pair_t *this, const char *value)
+{
+	assert(this);
+	lub_string_free(this->value);
+	this->value = lub_string_dup(value);
+}
+
+/*--------------------------------------------------------- */

+ 18 - 0
lub/ini/private.h

@@ -0,0 +1,18 @@
+/*
+ * lub/ini/private.h
+ *
+ * Class to parse ini-like strings/files.
+ */
+
+#include "lub/string.h"
+#include "lub/list.h"
+#include "lub/ini.h"
+
+struct lub_pair_s {
+	char *name;
+	char *value;
+};
+
+struct lub_ini_s {
+	lub_list_t *list;
+};

+ 4 - 1
lub/module.am

@@ -13,7 +13,8 @@ nobase_include_HEADERS += \
     lub/string.h \
     lub/types.h \
     lub/system.h \
-    lub/db.h
+    lub/db.h \
+    lub/ini.h
 
 EXTRA_DIST +=   \
     lub/argv/module.am \
@@ -24,6 +25,7 @@ EXTRA_DIST +=   \
     lub/string/module.am \
     lub/system/module.am \
     lub/db/module.am \
+    lub/ini/module.am \
     lub/README
 
 include $(top_srcdir)/lub/argv/module.am
@@ -34,3 +36,4 @@ include $(top_srcdir)/lub/dump/module.am
 include $(top_srcdir)/lub/string/module.am
 include $(top_srcdir)/lub/system/module.am
 include $(top_srcdir)/lub/db/module.am
+include $(top_srcdir)/lub/ini/module.am

+ 3 - 1
lub/string.h

@@ -269,7 +269,9 @@ char *lub_string_encode(const char *string, const char *escape_chars);
 char *lub_string_tolower(const char *str);
 unsigned int lub_string_equal_part(const char *str1, const char *str2,
 	bool_t utf8);
-
+const char *lub_string_nextword(const char *string,
+	size_t *len, size_t *offset, size_t *quoted);
+unsigned int lub_string_wordcount(const char *line);
 
 _END_C_DECL
 #endif				/* _lub_string_h */

+ 11 - 9
lub/string/module.am

@@ -1,10 +1,12 @@
-liblub_la_SOURCES +=	lub/string/string_cat.c	\
-			lub/string/string_catn.c	\
-			lub/string/string_dup.c	\
-			lub/string/string_free.c	\
-			lub/string/string_nocasecmp.c	\
-			lub/string/string_nocasestr.c	\
-			lub/string/string_suffix.c	\
-			lub/string/string_escape.c	\
-			lub/string/private.h
+liblub_la_SOURCES += \
+	lub/string/string_cat.c\
+	lub/string/string_catn.c \
+	lub/string/string_dup.c \
+	lub/string/string_free.c \
+	lub/string/string_nocasecmp.c \
+	lub/string/string_nocasestr.c \
+	lub/string/string_suffix.c \
+	lub/string/string_escape.c \
+	lub/string/string_word.c \
+	lub/string/private.h
 

+ 7 - 7
lub/argv/argv_nextword.c → lub/string/string_word.c

@@ -1,5 +1,5 @@
 /*
- * argv_nextword.c
+ * /lub/string/string_word.c
  */
 #include <stddef.h>
 #include <ctype.h>
@@ -8,8 +8,8 @@
 #include "lub/types.h"
 
 /*--------------------------------------------------------- */
-const char *lub_argv_nextword(const char *string,
-	size_t * len, size_t * offset, size_t * quoted)
+const char *lub_string_nextword(const char *string,
+	size_t *len, size_t *offset, size_t *quoted)
 {
 	const char *word;
 
@@ -60,16 +60,16 @@ const char *lub_argv_nextword(const char *string,
 }
 
 /*--------------------------------------------------------- */
-unsigned lub_argv_wordcount(const char *line)
+unsigned int lub_string_wordcount(const char *line)
 {
 	const char *word;
-	unsigned result = 0;
+	unsigned int result = 0;
 	size_t len = 0, offset = 0;
 	size_t quoted;
 
-	for (word = lub_argv_nextword(line, &len, &offset, &quoted);
+	for (word = lub_string_nextword(line, &len, &offset, &quoted);
 		*word || quoted;
-		word = lub_argv_nextword(word + len, &len, &offset, &quoted)) {
+		word = lub_string_nextword(word + len, &len, &offset, &quoted)) {
 		/* account for the terminating quotation mark */
 		len += quoted ? quoted - 1 : 0;
 		result++;