X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuci.git;a=blobdiff_plain;f=ucimap.c;h=455cf36e02a7fd4e3d37551eb45839e6bdb27d98;hp=cb86a4f34f61219645204e069245f666bfd8735a;hb=3fa4e980d9dd281ad556069e09d17ba64ef4156d;hpb=f107b5a34f5f20ff373683472cfa5978da640132 diff --git a/ucimap.c b/ucimap.c index cb86a4f..455cf36 100644 --- a/ucimap.c +++ b/ucimap.c @@ -27,28 +27,12 @@ struct uci_alloc { struct uci_fixup { struct list_head list; - struct uci_sectmap *sm; + struct uci_sectionmap *sm; const char *name; enum ucimap_type type; union ucimap_data *data; }; -struct uci_sectmap_data { - struct list_head list; - struct uci_map *map; - struct uci_sectmap *sm; - const char *section_name; - - /* list of allocations done by ucimap */ - struct uci_alloc *allocmap; - unsigned long allocmap_len; - - /* map for changed fields */ - unsigned char *cmap; - bool done; -}; - - #define ucimap_foreach_option(_sm, _o) \ if (!(_sm)->options_size) \ (_sm)->options_size = sizeof(struct uci_optmap); \ @@ -93,12 +77,24 @@ ucimap_is_list(enum ucimap_type type) return ((type & UCIMAP_TYPE) == UCIMAP_LIST); } +static inline bool +ucimap_is_custom(enum ucimap_type type) +{ + return ((type & UCIMAP_SUBTYPE) == UCIMAP_CUSTOM); +} + +static inline void * +ucimap_section_ptr(struct ucimap_section_data *sd) +{ + return ((char *) sd - sd->sm->smap_offset); +} + static inline union ucimap_data * -ucimap_get_data(struct uci_sectmap_data *sd, struct uci_optmap *om) +ucimap_get_data(struct ucimap_section_data *sd, struct uci_optmap *om) { void *data; - data = (char *) sd + sizeof(struct uci_sectmap_data) + om->offset; + data = (char *) ucimap_section_ptr(sd) + om->offset; return data; } @@ -122,7 +118,7 @@ ucimap_free_item(struct uci_alloc *a) } static void -ucimap_add_alloc(struct uci_sectmap_data *sd, void *ptr) +ucimap_add_alloc(struct ucimap_section_data *sd, void *ptr) { struct uci_alloc *a = &sd->allocmap[sd->allocmap_len++]; a->type = UCIMAP_SIMPLE; @@ -130,17 +126,17 @@ ucimap_add_alloc(struct uci_sectmap_data *sd, void *ptr) } static void -ucimap_free_section(struct uci_map *map, struct uci_sectmap_data *sd) +ucimap_free_section(struct uci_map *map, struct ucimap_section_data *sd) { - void *section = sd; + void *section; int i; - section = (char *) section + sizeof(struct uci_sectmap_data); + section = ucimap_section_ptr(sd); if (!list_empty(&sd->list)) list_del(&sd->list); - if (sd->sm->free_section) - sd->sm->free_section(map, section); + if (sd->sm->free) + sd->sm->free(map, section); for (i = 0; i < sd->allocmap_len; i++) { ucimap_free_item(&sd->allocmap[i]); @@ -156,7 +152,7 @@ ucimap_cleanup(struct uci_map *map) struct list_head *ptr, *tmp; list_for_each_safe(ptr, tmp, &map->sdata) { - struct uci_sectmap_data *sd = list_entry(ptr, struct uci_sectmap_data, list); + struct ucimap_section_data *sd = list_entry(ptr, struct ucimap_section_data, list); ucimap_free_section(map, sd); } } @@ -179,15 +175,15 @@ ucimap_add_fixup(struct uci_map *map, union ucimap_data *data, struct uci_optmap } static void -ucimap_add_value(union ucimap_data *data, struct uci_optmap *om, struct uci_sectmap_data *sd, const char *str) +ucimap_add_value(union ucimap_data *data, struct uci_optmap *om, struct ucimap_section_data *sd, const char *str) { - union ucimap_data *tdata = data; + union ucimap_data tdata = *data; char *eptr = NULL; char *s; int val; if (ucimap_is_list(om->type) && !ucimap_is_fixup(om->type)) - tdata = &data->list->item[data->list->n_items++]; + data = &data->list->item[data->list->n_items++]; switch(om->type & UCIMAP_SUBTYPE) { case UCIMAP_STRING: @@ -196,7 +192,7 @@ ucimap_add_value(union ucimap_data *data, struct uci_optmap *om, struct uci_sect return; s = strdup(str); - tdata->s = s; + tdata.s = s; ucimap_add_alloc(sd, s); break; case UCIMAP_BOOL: @@ -216,24 +212,34 @@ ucimap_add_value(union ucimap_data *data, struct uci_optmap *om, struct uci_sect if (val == -1) return; - tdata->b = val; + tdata.b = val; break; case UCIMAP_INT: val = strtol(str, &eptr, om->data.i.base); if (!eptr || *eptr == '\0') - tdata->i = val; + tdata.i = val; else return; break; case UCIMAP_SECTION: ucimap_add_fixup(sd->map, data, om, str); + return; + case UCIMAP_CUSTOM: + tdata.s = (char *) data; break; } + if (om->parse) { + if (om->parse(ucimap_section_ptr(sd), om, &tdata, str) < 0) + return; + } + if (ucimap_is_custom(om->type)) + return; + memcpy(data, &tdata, sizeof(union ucimap_data)); } static int -ucimap_parse_options(struct uci_map *map, struct uci_sectmap *sm, struct uci_sectmap_data *sd, struct uci_section *s) +ucimap_parse_options(struct uci_map *map, struct uci_sectionmap *sm, struct ucimap_section_data *sd, struct uci_section *s) { struct uci_element *e, *l; struct uci_option *o; @@ -267,21 +273,23 @@ ucimap_parse_options(struct uci_map *map, struct uci_sectmap *sm, struct uci_sec static int -ucimap_parse_section(struct uci_map *map, struct uci_sectmap *sm, struct uci_section *s) +ucimap_parse_section(struct uci_map *map, struct uci_sectionmap *sm, struct uci_section *s) { - struct uci_sectmap_data *sd = NULL; + struct ucimap_section_data *sd = NULL; struct uci_optmap *om; char *section_name; void *section; int n_alloc = 2; int err; - sd = malloc(sm->alloc_len + sizeof(struct uci_sectmap_data)); + sd = malloc(sm->alloc_len); if (!sd) return UCI_ERR_MEM; - memset(sd, 0, sm->alloc_len + sizeof(struct uci_sectmap_data)); + memset(sd, 0, sm->alloc_len); INIT_LIST_HEAD(&sd->list); + sd->map = map; + sd->sm = sm; ucimap_foreach_option(sm, om) { if (ucimap_is_list(om->type)) { @@ -313,8 +321,6 @@ ucimap_parse_section(struct uci_map *map, struct uci_sectmap *sm, struct uci_sec } } - sd->map = map; - sd->sm = sm; sd->allocmap = malloc(n_alloc * sizeof(struct uci_alloc)); if (!sd->allocmap) goto error_mem; @@ -339,9 +345,8 @@ ucimap_parse_section(struct uci_map *map, struct uci_sectmap *sm, struct uci_sec ucimap_add_alloc(sd, ucimap_get_data(sd, om)->list); } - section = (char *)sd + sizeof(struct uci_sectmap_data); - - err = sm->init_section(map, section, s); + section = ucimap_section_ptr(sd); + err = sm->init(map, section, s); if (err) goto error; @@ -381,11 +386,10 @@ ucimap_fill_ptr(struct uci_ptr *ptr, struct uci_section *s, const char *option) } void -ucimap_set_changed(void *section, void *field) +ucimap_set_changed(struct ucimap_section_data *sd, void *field) { - char *sptr = (char *)section - sizeof(struct uci_sectmap_data); - struct uci_sectmap_data *sd = (struct uci_sectmap_data *) sptr; - struct uci_sectmap *sm = sd->sm; + void *section = ucimap_section_ptr(sd); + struct uci_sectionmap *sm = sd->sm; struct uci_optmap *om; int ofs = (char *)field - (char *)section; int i = 0; @@ -402,9 +406,9 @@ ucimap_set_changed(void *section, void *field) int ucimap_store_section(struct uci_map *map, struct uci_package *p, void *section) { - char *sptr = (char *)section - sizeof(struct uci_sectmap_data); - struct uci_sectmap_data *sd = (struct uci_sectmap_data *) sptr; - struct uci_sectmap *sm = sd->sm; + 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; struct uci_element *e; @@ -426,6 +430,9 @@ ucimap_store_section(struct uci_map *map, struct uci_package *p, void *section) static char buf[32]; const char *str = NULL; + if (ucimap_is_list(om->type)) + continue; + data = ucimap_get_data(sd, om); if (!TEST_BIT(sd->cmap, i)) continue; @@ -443,6 +450,8 @@ ucimap_store_section(struct uci_map *map, struct uci_package *p, void *section) sprintf(buf, "%d", !!data->b); str = buf; break; + default: + continue; } ptr.value = str; @@ -460,18 +469,16 @@ ucimap_store_section(struct uci_map *map, struct uci_package *p, void *section) void * ucimap_find_section(struct uci_map *map, struct uci_fixup *f) { - struct uci_sectmap_data *sd; + struct ucimap_section_data *sd; struct list_head *p; - void *ret; list_for_each(p, &map->sdata) { - sd = list_entry(p, struct uci_sectmap_data, list); + sd = list_entry(p, struct ucimap_section_data, list); if (sd->sm != f->sm) continue; if (strcmp(f->name, sd->section_name) != 0) continue; - ret = (char *)sd + sizeof(struct uci_sectmap_data); - return ret; + return ucimap_section_ptr(sd); } return NULL; } @@ -513,14 +520,14 @@ ucimap_parse(struct uci_map *map, struct uci_package *pkg) free(f); } list_for_each_safe(p, tmp, &map->sdata) { - struct uci_sectmap_data *sd = list_entry(p, struct uci_sectmap_data, list); + struct ucimap_section_data *sd = list_entry(p, struct ucimap_section_data, list); void *section; if (sd->done) continue; - section = (char *) sd + sizeof(struct uci_sectmap_data); - if (sd->sm->add_section(map, section) != 0) + section = ucimap_section_ptr(sd); + if (sd->sm->add(map, section) != 0) ucimap_free_section(map, sd); } }