Browse Source

ucimap: implement format callback for custom data types

Felix Fietkau 14 years ago
parent
commit
82a71ad8d8
3 changed files with 39 additions and 11 deletions
  1. 16 3
      ucimap-example.c
  2. 21 7
      ucimap.c
  3. 2 1
      ucimap.h

+ 16 - 3
ucimap-example.c

@@ -58,6 +58,18 @@ network_parse_ip(void *section, struct uci_optmap *om, union ucimap_data *data,
 	return 0;
 }
 
+static int
+network_format_ip(void *sction, struct uci_optmap *om, union ucimap_data *data, char **str)
+{
+	static char buf[16];
+	unsigned char *ip = (unsigned char *) data->s;
+
+	sprintf(buf, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
+	*str = buf;
+
+	return 0;
+}
+
 static int
 network_init_interface(struct uci_map *map, void *section, struct uci_section *s)
 {
@@ -139,6 +151,7 @@ static struct my_optmap network_interface_options[] = {
 			.type = UCIMAP_CUSTOM,
 			.name = "ipaddr",
 			.parse = network_parse_ip,
+			.format = network_format_ip,
 		}
 	},
 	{
@@ -241,9 +254,9 @@ int main(int argc, char **argv)
 			printf("New alias: %s\n", alias->name);
 		}
 #if 0
-		net->ipaddr = "2.3.4.5";
-		ucimap_set_changed(net, &net->ipaddr);
-		ucimap_store_section(&network_map, pkg, net);
+		memcpy(net->ipaddr, "\x01\x03\x04\x05", 4);
+		ucimap_set_changed(&net->map, &net->ipaddr);
+		ucimap_store_section(&network_map, pkg, &net->map);
 		uci_save(ctx, pkg);
 #endif
 	}

+ 21 - 7
ucimap.c

@@ -410,10 +410,8 @@ ucimap_set_changed(struct ucimap_section_data *sd, void *field)
 }
 
 int
-ucimap_store_section(struct uci_map *map, struct uci_package *p, void *section)
+ucimap_store_section(struct uci_map *map, struct uci_package *p, struct ucimap_section_data *sd)
 {
-	char *sptr = (char *)section - sizeof(struct ucimap_section_data);
-	struct ucimap_section_data *sd = (struct ucimap_section_data *) sptr;
 	struct uci_sectionmap *sm = sd->sm;
 	struct uci_section *s = NULL;
 	struct uci_optmap *om;
@@ -434,13 +432,14 @@ ucimap_store_section(struct uci_map *map, struct uci_package *p, void *section)
 	ucimap_foreach_option(sm, om) {
 		union ucimap_data *data;
 		static char buf[32];
-		const char *str = NULL;
+		char *str = NULL;
 
+		i++;
 		if (ucimap_is_list(om->type))
 			continue;
 
 		data = ucimap_get_data(sd, om);
-		if (!TEST_BIT(sd->cmap, i))
+		if (!TEST_BIT(sd->cmap, i - 1))
 			continue;
 
 		ucimap_fill_ptr(&ptr, s, om->name);
@@ -456,17 +455,32 @@ ucimap_store_section(struct uci_map *map, struct uci_package *p, void *section)
 			sprintf(buf, "%d", !!data->b);
 			str = buf;
 			break;
+		case UCIMAP_CUSTOM:
+			break;
 		default:
 			continue;
 		}
+		if (om->format) {
+			union ucimap_data tdata, *data;
+
+			data = ucimap_get_data(sd, om);
+			if (ucimap_is_custom(om->type)) {
+				tdata.s = (char *)data;
+				data = &tdata;
+			}
+
+			if (om->format(ucimap_section_ptr(sd), om, data, &str) < 0)
+				continue;
+		}
+		if (!str)
+			continue;
 		ptr.value = str;
 
 		ret = uci_set(s->package->ctx, &ptr);
 		if (ret)
 			return ret;
 
-		CLR_BIT(sd->cmap, i);
-		i++;
+		CLR_BIT(sd->cmap, i - 1);
 	}
 
 	return 0;

+ 2 - 1
ucimap.h

@@ -133,6 +133,7 @@ struct uci_optmap {
 	const char *name;
 	enum ucimap_type type;
 	int (*parse)(void *section, struct uci_optmap *om, union ucimap_data *data, const char *string);
+	int (*format)(void *section, struct uci_optmap *om, union ucimap_data *data, char **string);
 	union {
 		struct {
 			int base;
@@ -154,6 +155,6 @@ struct ucimap_list {
 extern int ucimap_init(struct uci_map *map);
 extern void ucimap_cleanup(struct uci_map *map);
 extern void ucimap_set_changed(struct ucimap_section_data *sd, void *field);
-extern int ucimap_store_section(struct uci_map *map, struct uci_package *p, void *section);
+extern int ucimap_store_section(struct uci_map *map, struct uci_package *p, struct ucimap_section_data *sd);
 extern void ucimap_parse(struct uci_map *map, struct uci_package *pkg);