Browse Source

ucimap: add new UCIMAP_LIST_AUTO for automatically converting multiple list items whitespace-separated in an option

Felix Fietkau 14 years ago
parent
commit
477c19a722
5 changed files with 81 additions and 5 deletions
  1. 7 0
      test/config/network
  2. 3 1
      test/references/ucimap_example.result
  3. 1 1
      ucimap-example.c
  4. 65 3
      ucimap.c
  5. 5 0
      ucimap.h

+ 7 - 0
test/config/network

@@ -17,4 +17,11 @@ config 'interface' 'wan'
 	option 'proto'	'dhcp'
 	option 'ifname' 'eth1'
 	option 'enabled' 'on'
+	option 'aliases' 'c d'
+	
+config 'alias' 'c'
+	option 'interface' 'wan'
+
+config 'alias' 'd'
+	option 'interface' 'wan'
 

+ 3 - 1
test/references/ucimap_example.result

@@ -4,11 +4,13 @@ New network section 'lan'
 	ipaddr: 2.3.4.5
 	test: 123
 	enabled: off
-New alias: b
 New alias: a
+New alias: b
 New network section 'wan'
 	type: dhcp
 	ifname: eth1
 	ipaddr: 0.0.0.0
 	test: -1
 	enabled: on
+New alias: c
+New alias: d

+ 1 - 1
ucimap-example.c

@@ -170,7 +170,7 @@ static struct my_optmap network_interface_options[] = {
 	{
 		.map = {
 			UCIMAP_OPTION(struct uci_network, aliases),
-			.type = UCIMAP_LIST | UCIMAP_SECTION,
+			.type = UCIMAP_LIST | UCIMAP_SECTION | UCIMAP_LIST_AUTO,
 			.data.sm = &network_alias
 		}
 	}

+ 65 - 3
ucimap.c

@@ -17,6 +17,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <limits.h>
+#include <ctype.h>
 #include "ucimap.h"
 
 struct uci_alloc {
@@ -78,6 +79,12 @@ ucimap_is_list(enum ucimap_type type)
 	return ((type & UCIMAP_TYPE) == UCIMAP_LIST);
 }
 
+static inline bool
+ucimap_is_list_auto(enum ucimap_type type)
+{
+	return ucimap_is_list(type) && !!(type & UCIMAP_LIST_AUTO);
+}
+
 static inline bool
 ucimap_is_custom(enum ucimap_type type)
 {
@@ -172,7 +179,7 @@ ucimap_add_fixup(struct uci_map *map, union ucimap_data *data, struct uci_optmap
 	f->name = str;
 	f->type = om->type;
 	f->data = data;
-	list_add(&f->list, &map->fixup);
+	list_add_tail(&f->list, &map->fixup);
 }
 
 static void
@@ -242,6 +249,37 @@ ucimap_add_value(union ucimap_data *data, struct uci_optmap *om, struct ucimap_s
 }
 
 
+static void
+ucimap_convert_list(union ucimap_data *data, struct uci_optmap *om, struct ucimap_section_data *sd, const char *str)
+{
+	char *s, *p;
+
+	s = strdup(str);
+	if (!s)
+		return;
+
+	ucimap_add_alloc(sd, s);
+
+	do {
+		while (isspace(*s))
+			s++;
+
+		if (!*s)
+			break;
+
+		p = s;
+		while (*s && !isspace(*s))
+			s++;
+
+		if (isspace(*s)) {
+			*s = 0;
+			s++;
+		}
+
+		ucimap_add_value(data, om, sd, p);
+	} while (*s);
+}
+
 static int
 ucimap_parse_options(struct uci_map *map, struct uci_sectionmap *sm, struct ucimap_section_data *sd, struct uci_section *s)
 {
@@ -269,6 +307,8 @@ ucimap_parse_options(struct uci_map *map, struct uci_sectionmap *sm, struct ucim
 			uci_foreach_element(&o->v.list, l) {
 				ucimap_add_value(data, om, sd, l->name);
 			}
+		} else if ((o->type == UCI_TYPE_STRING) && ucimap_is_list_auto(om->type)) {
+			ucimap_convert_list(data, om, sd, o->v.string);
 		}
 	}
 
@@ -316,11 +356,33 @@ ucimap_parse_section(struct uci_map *map, struct uci_sectionmap *sm, struct uci_
 				if (strcmp(e->name, om->name) != 0)
 					continue;
 
-				uci_foreach_element(&o->v.list, tmp) {
-					n_elements++;
+				if (o->type == UCI_TYPE_LIST) {
+					uci_foreach_element(&o->v.list, tmp) {
+						n_elements++;
+					}
+				} else if ((o->type == UCI_TYPE_STRING) &&
+				           ucimap_is_list_auto(om->type)) {
+					const char *data = o->v.string;
+					do {
+						while (isspace(*data))
+							data++;
+
+						if (!*data)
+							break;
+
+						n_elements++;
+
+						while (*data && !isspace(*data))
+							data++;
+					} while (*data);
+
+					/* for the duplicated data string */
+					if (n_elements > 0)
+						n_alloc++;
 				}
 				break;
 			}
+			/* add one more for the ucimap_list */
 			n_alloc += n_elements + 1;
 			size = sizeof(struct ucimap_list) +
 				n_elements * sizeof(union ucimap_data);

+ 5 - 0
ucimap.h

@@ -68,6 +68,11 @@ enum ucimap_type {
 	UCIMAP_SECTION  = 0x3,
 	UCIMAP_CUSTOM	= 0x4,
 	UCIMAP_SUBTYPE  = 0xf, /* subtype mask */
+
+	/* automatically create lists from
+	 * options with space-separated items */
+	UCIMAP_LIST_AUTO = 0x0100,
+	UCIMAP_FLAGS     = 0xff00, /* flags mask */
 };
 
 union ucimap_data {