diff ini.c @ 95:cb5d3d66ea04

Merge
author David Demelier <markand@malikania.fr>
date Thu, 12 Jan 2012 20:12:48 +0100
parents 145493469aa0
children dcaf2c61c902
line wrap: on
line diff
--- a/ini.c	Thu Jan 12 15:42:08 2012 +0100
+++ b/ini.c	Thu Jan 12 20:12:48 2012 +0100
@@ -26,9 +26,9 @@
 
 #include "ini.h"
 
-/* --------------------------------------------------------
- * structure definitions
- * -------------------------------------------------------- */
+/* -------------------------------------------------------- */
+/* structure definitions				    */
+/* -------------------------------------------------------- */
 
 struct ini_option {
 	char		*key;		/* option name */
@@ -59,11 +59,11 @@
 	STAILQ_HEAD(, ini_section) sections;
 };
 
-static char	iniError[1024 + 1];
+static char	ini_error[1024 + 1];
 
-/* --------------------------------------------------------
- * prototypes
- * -------------------------------------------------------- */
+/* -------------------------------------------------------- */
+/* prototypes						    */
+/* -------------------------------------------------------- */
 
 static void	*ini_read(struct ini_config *, FILE *);
 static int	ini_getline(struct ini_config *, FILE *);
@@ -119,7 +119,7 @@
  */
 
 char **
-ini_get_sections_names(struct ini_config *conf, int *number)
+ini_get_sections_names(const struct ini_config *conf, int *number)
 {
 	struct ini_section *s;
 	char **list;
@@ -129,6 +129,10 @@
 	STAILQ_FOREACH(s, &conf->sections, next)
 		++ i;
 
+	/* For safety */
+	if (number != NULL)
+		*number = 0;
+
 	if ((list = calloc(i + 1, sizeof (char *))) == NULL)
 		return NULL;
 
@@ -188,7 +192,7 @@
  */
 
 struct ini_section *
-ini_select_section(struct ini_config *conf, const char *section)
+ini_select_section(const struct ini_config *conf, const char *section)
 {
 	struct ini_section *s;
 
@@ -207,7 +211,7 @@
  */
 
 char *
-ini_option_once(struct ini_config *conf, const char *sect, const char *key)
+ini_get_option_once(const struct ini_config *conf, const char *sect, const char *key)
 {
 	struct ini_option *o;
 	struct ini_section *s;
@@ -228,7 +232,7 @@
  */
 
 char **
-ini_get_option_names(struct ini_section *section, int *nb)
+ini_get_option_names(const struct ini_section *section, int *nb)
 {
 	char **list;
 	struct ini_option *o;
@@ -238,6 +242,9 @@
 	STAILQ_FOREACH(o, &section->options, next)
 		++ i;
 
+	if (nb != NULL)
+		*nb = i;
+
 	if ((list = calloc(i + 1, sizeof (char *))) == NULL)
 		return NULL;
 
@@ -258,7 +265,7 @@
  */
 
 char *
-ini_get_option(struct ini_section *section, const char *key)
+ini_get_option(const struct ini_section *section, const char *key)
 {
 	struct ini_option *o;
 
@@ -270,16 +277,101 @@
 }
 
 /*
+ * These section provide very small API to convert value
+ * and store them to the dst pointer. Because you can also
+ * use your own handlers, the user data here can't be used.
+ */
+
+void
+ini_value_dispatch(struct ini_config *config, struct ini_handler *hdrs, int length)
+{
+	const char *sectionName;
+	int i;
+	char *value;
+	struct ini_section *section;
+
+	sectionName = NULL;
+	for (i = 0; i < length; ++i) {
+		/* Do not select the same section for performance. */
+		if (sectionName == NULL || strcmp(hdrs[i].section, sectionName) != 0) {
+			sectionName	= hdrs[i].section;
+			section		= ini_select_section(config, hdrs[i].section);
+		}
+
+		/* Skip the section if does not exists in the config */
+		if (section == NULL)
+			continue;
+
+		value = ini_get_option(section, hdrs[i].option);
+		hdrs[i].handler(hdrs[i].dst, value, hdrs[i].userdata);
+	}
+}
+
+void
+ini_convert_bool(void *dst, const char *value, void *dummy)
+{
+	char *p = dst;
+
+	if (value == NULL)
+		return ;
+
+	if (strcmp(value, "yes") == 0 ||
+	    strcmp(value, "true") == 0 ||
+	    strcmp(value, "1") == 0)
+		*p = 1;
+	else
+		*p = 0;
+	(void)dummy;
+}
+
+void
+ini_convert_int(void *dst, const char *value, void *dummy)
+{
+	int *p = dst;
+
+	if (value == NULL)
+		return ;
+
+	*p = (int) strtol(value, NULL, 10);
+	(void)dummy;
+}
+
+void
+ini_convert_short(void *dst, const char *value, void *dummy)
+{
+	short *p = dst;
+
+	if (value == NULL)
+		return ;
+
+	*p = (short) strtol(value, NULL, 10);
+	(void)dummy;
+}
+
+void
+ini_convert_string(void *dst, const char *value, void *dummy)
+{
+	char **p = dst;
+
+	if (value == NULL)
+		*p = NULL;
+	else
+		*p = strdup(value);
+
+	(void)dummy;
+}
+
+/*
  * Return the last error or "No error" if there is not error at all.
  */
 
 char *
-ini_error(void)
+ini_get_error(void)
 {
-	if (iniError[0] == '\0')
+	if (ini_error[0] == '\0')
 		return "No error";
 
-	return iniError;
+	return ini_error;
 }
 
 void
@@ -410,8 +502,10 @@
 			handler = &ini_switch;
 		else if (!conf->ignore)
 			handler = &ini_register;
-		else
+		else {
 			handler = NULL;
+			++ lp;
+		}
 
 		/* Success or not? */
 		if (handler != NULL && handler(conf, &lp) < 0)
@@ -522,7 +616,8 @@
 	/* Find end of option value */
 	token = *endValue;
 	if (token == '\'' || token == '"') {
-		for (*lp = ++endValue; *endValue != token && *endValue != '\0'; ++endValue)
+		for (*lp = ++endValue; *endValue != token &&
+		    *endValue != '\0'; ++endValue)
 			continue;
 
 		length = endValue - *lp;
@@ -533,7 +628,8 @@
 		else
 			WARN(conf, "line %d: missing '%c'\n", conf->lineno, token);
 	} else {
-		for (*lp = endValue; !isspace(*endValue) && *endValue != '\0'; ++endValue)
+		for (*lp = endValue; !isspace(*endValue) && *endValue != '\0' && 
+		    *endValue != '#' && *endValue != ';'; ++endValue)
 			continue;
 
 		length = endValue - *lp;
@@ -588,11 +684,11 @@
 		fclose(fp);
 
 	va_start(ap, fmt);
-	vsnprintf(iniError, 1024, fmt, ap);
+	vsnprintf(ini_error, 1024, fmt, ap);
 	va_end(ap);
 
 	/* Directly print error if VERBOSE is enabled */
-	WARN(conf, "%s\n", iniError);
+	WARN(conf, "%s\n", ini_error);
 
 	free(conf);