ucimap: add new UCIMAP_LIST_AUTO for automatically converting multiple list items...
authorFelix Fietkau <nbd@openwrt.org>
Mon, 31 Aug 2009 20:44:34 +0000 (22:44 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Mon, 31 Aug 2009 20:44:34 +0000 (22:44 +0200)
test/config/network
test/references/ucimap_example.result
ucimap-example.c
ucimap.c
ucimap.h

index b201c48..6e2b5cc 100644 (file)
@@ -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'
 
index c3dfb68..4a20965 100644 (file)
@@ -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
index 157c32f..affb070 100644 (file)
@@ -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
                }
        }
index 7dba62a..b1ba853 100644 (file)
--- a/ucimap.c
+++ b/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);
index ccd6127..a114644 100644 (file)
--- a/ucimap.h
+++ b/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 {