[PATCH] Add new config parser

Kristian Høgsberg krh at bitplanet.net
Mon Apr 1 09:42:25 PDT 2013


The current config parser, parses the ini file and pulls out the values
specified by the struct config_section passed to parse_config_file() and
then throw the rest away.  This means that every place we want to get
info out of the ini file, we have to parse the whole thing again.  It's not
a big overhead, but it's also not a convenient API.

This patch adds a parser that parses the ini file to a data structure and
puts that in weston_compositor->config along with API to query comfig
keys from the data structure.  The old parser is still available, but
we'll transition to the new approach over the next few commits.
---
 shared/config-parser.c | 225 +++++++++++++++++++++++++++++++++++++++++++++++++
 shared/config-parser.h |  26 ++++++
 src/compositor.c       |   2 +
 src/compositor.h       |   1 +
 4 files changed, 254 insertions(+)

diff --git a/shared/config-parser.c b/shared/config-parser.c
index 10ff86a..5582cc4 100644
--- a/shared/config-parser.c
+++ b/shared/config-parser.c
@@ -25,7 +25,9 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <ctype.h>
+#include <errno.h>
 
+#include <wayland-util.h>
 #include "config-parser.h"
 
 static int
@@ -185,3 +187,226 @@ config_file_path(const char *name)
 	snprintf(path, size, "%s/%s", config_dir, name);
 	return path;
 }
+
+struct weston_config_entry {
+	char *key;
+	char *value;
+	struct wl_list link;
+};
+
+struct weston_config_section {
+	char *name;
+	struct wl_list entry_list;
+	struct wl_list link;
+};
+
+struct weston_config {
+	struct wl_list section_list;
+};
+
+struct weston_config_section *
+weston_config_get_section(struct weston_config *config, const char *section)
+{
+	struct weston_config_section *s;
+
+	wl_list_for_each(s, &config->section_list, link)
+		if (strcmp(s->name, section) == 0)
+			return s;
+
+	return NULL;
+}
+
+static struct weston_config_entry *
+config_section_get_entry(struct weston_config_section *section,
+			 const char *key)
+{
+	struct weston_config_entry *e;
+
+	if (section == NULL)
+		return NULL;
+	wl_list_for_each(e, &section->entry_list, link)
+		if (strcmp(e->key, key) == 0)
+			return e;
+
+	return NULL;
+}
+
+int
+weston_config_section_get_int(struct weston_config_section *section,
+			      const char *key,
+			      int32_t *value, int32_t default_value)
+{
+	struct weston_config_entry *entry;
+	char *end;
+
+	entry = config_section_get_entry(section, key);
+	if (entry == NULL) {
+		*value = default_value;
+		errno = ENOENT;
+		return -1;
+	}
+
+	*value = strtol(entry->value, &end, 0);
+	if (*end != '\0') {
+		*value = default_value;
+		errno = EINVAL;
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+weston_config_section_get_uint(struct weston_config_section *section,
+			       const char *key,
+			       uint32_t *value, uint32_t default_value)
+{
+	struct weston_config_entry *entry;
+	char *end;
+
+	entry = config_section_get_entry(section, key);
+	if (entry == NULL) {
+		*value = default_value;
+		errno = ENOENT;
+		return -1;
+	}
+
+	*value = strtoul(entry->value, &end, 0);
+	if (*end != '\0') {
+		*value = default_value;
+		errno = EINVAL;
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+weston_config_section_get_string(struct weston_config_section *section,
+				 const char *key,
+				 const char **value, const char *default_value)
+{
+	struct weston_config_entry *entry;
+
+	entry = config_section_get_entry(section, key);
+	if (entry == NULL) {
+		if (default_value)
+			*value = strdup(default_value);
+		errno = ENOENT;
+		return -1;
+	}
+
+	*value = strdup(entry->value);
+
+	return 0;
+}
+
+int
+weston_config_section_get_bool(struct weston_config_section *section,
+			       const char *key,
+			       int *value, int default_value)
+{
+	struct weston_config_entry *entry;
+
+	entry = config_section_get_entry(section, key);
+	if (entry == NULL) {
+		*value = default_value;
+		errno = ENOENT;
+		return -1;
+	}
+
+	if (strcmp(entry->value, "false\n") == 0)
+		*value = 0;
+	else if (strcmp(entry->value, "true\n") == 0)
+		*value = 1;
+	else {
+		*value = default_value;
+		errno = EINVAL;
+		return -1;
+	}
+
+	return 0;
+}
+
+static struct weston_config_section *
+config_add_section(struct weston_config *config, const char *name)
+{
+	struct weston_config_section *section;
+
+	section = malloc(sizeof *section);
+	section->name = strdup(name);
+	wl_list_init(&section->entry_list);
+	wl_list_insert(config->section_list.prev, &section->link);
+
+	return section;
+}
+
+static struct weston_config_entry *
+section_add_entry(struct weston_config_section *section,
+		  const char *key, const char *value)
+{
+	struct weston_config_entry *entry;
+
+	entry = malloc(sizeof *entry);
+	entry->key = strdup(key);
+	entry->value = strdup(value);
+	wl_list_insert(section->entry_list.prev, &entry->link);
+
+	return entry;
+}
+
+struct weston_config *
+weston_config_parse(const char *path)
+{
+	FILE *fp;
+	char line[512], *p;
+	struct weston_config *config;
+	struct weston_config_section *section = NULL;
+	int i;
+
+	config = malloc(sizeof *config);
+	if (config == NULL) {
+		free(path);
+		return NULL;
+	}
+
+	wl_list_init(&config->section_list);
+
+	fp = fopen(path, "r");
+	if (fp == NULL) {
+		fprintf(stderr, "couldn't open %s\n", path);
+		free(config);
+		return NULL;
+	}
+
+	while (fgets(line, sizeof line, fp)) {
+		if (line[0] == '#' || line[0] == '\n') {
+			continue;
+		} if (line[0] == '[') {
+			p = strchr(&line[1], ']');
+			if (!p || p[1] != '\n') {
+				fprintf(stderr, "malformed "
+					"section header: %s\n", line);
+				fclose(fp);
+				free(config);
+				return NULL;
+			}
+			p[0] = '\0';
+			section = config_add_section(config, &line[1]);
+		} else if (p = strchr(line, '='), p && section) {
+			p[0] = '\0';
+			i = strlen(&p[1]);
+			p[i + 1] = '\0';
+			section_add_entry(section, line, &p[1]);
+		} else {
+			fprintf(stderr, "malformed config line: %s\n", line);
+			fclose(fp);
+			free(config);
+			return NULL;
+		}
+	}
+
+	fclose(fp);
+
+	return config;
+}
diff --git a/shared/config-parser.h b/shared/config-parser.h
index 1d0ee3f..0efbac3 100644
--- a/shared/config-parser.h
+++ b/shared/config-parser.h
@@ -73,6 +73,32 @@ int
 parse_options(const struct weston_option *options,
 	      int count, int *argc, char *argv[]);
 
+struct weston_config_section;
+struct weston_config;
+
+struct weston_config_section *
+weston_config_get_section(struct weston_config *config, const char *section);
+int
+weston_config_section_get_int(struct weston_config_section *section,
+			      const char *key,
+			      int32_t *value, int32_t default_value);
+int
+weston_config_section_get_uint(struct weston_config_section *section,
+			       const char *key,
+			       uint32_t *value, uint32_t default_value);
+int
+weston_config_section_get_string(struct weston_config_section *section,
+				 const char *key,
+				 const char **value,
+				 const char *default_value);
+int
+weston_config_section_get_bool(struct weston_config_section *section,
+			       const char *key,
+			       int *value, int default_value);
+struct weston_config *
+weston_config_parse(const char *basename);
+
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/src/compositor.c b/src/compositor.c
index 1617d96..cb374f7 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3139,6 +3139,8 @@ weston_compositor_init(struct weston_compositor *ec,
                   keyboard_config_keys, ARRAY_LENGTH(keyboard_config_keys) },
 	};
 
+	ec->config = weston_config_parse(config_file);
+
 	memset(&xkb_names, 0, sizeof(xkb_names));
 	parse_config_file(config_file, cs, ARRAY_LENGTH(cs), ec);
 
diff --git a/src/compositor.h b/src/compositor.h
index 7d1d68e..e4c7ab2 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -301,6 +301,7 @@ struct weston_compositor {
 
 	struct wl_display *wl_display;
 	struct weston_shell_interface shell_interface;
+	struct weston_config *config;
 
 	struct wl_signal activate_signal;
 	struct wl_signal kill_signal;
-- 
1.8.1.2



More information about the wayland-devel mailing list