X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=ucimap.c;h=b477264b23dca1b905784bddb8fd6d32de2d9ad0;hb=c81b25ffd34632dc6ac56fe61faaf44eca822259;hp=3d11c590270a040c43a010a8baeb1a17cb381b1b;hpb=ba0d03d0cca59b5b8d30f4844d9eb9ec3e87c69a;p=uci.git diff --git a/ucimap.c b/ucimap.c index 3d11c59..b477264 100644 --- a/ucimap.c +++ b/ucimap.c @@ -1,9 +1,9 @@ /* - * ucimap - library for mapping uci sections into data structures - * Copyright (C) 2008 Felix Fietkau + * ucimap.c - Library for the Unified Configuration Interface + * Copyright (C) 2008-2009 Felix Fietkau * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 + * it under the terms of the GNU Lesser General Public License version 2.1 * as published by the Free Software Foundation * * This program is distributed in the hope that it will be useful, @@ -11,6 +11,11 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ + +/* + * This file contains ucimap, an API for mapping UCI to C data structures + */ + #include #include #include @@ -23,18 +28,18 @@ #include "ucimap.h" #include "uci_internal.h" -struct uci_alloc { +struct ucimap_alloc { void *ptr; }; -struct uci_alloc_custom { +struct ucimap_alloc_custom { void *section; struct uci_optmap *om; void *ptr; }; -struct uci_fixup { - struct list_head list; +struct ucimap_fixup { + struct ucimap_fixup *next; struct uci_sectionmap *sm; const char *name; enum ucimap_type type; @@ -121,16 +126,17 @@ ucimap_get_data(struct ucimap_section_data *sd, struct uci_optmap *om) int ucimap_init(struct uci_map *map) { - INIT_LIST_HEAD(&map->pending); - INIT_LIST_HEAD(&map->sdata); - INIT_LIST_HEAD(&map->fixup); + map->fixup = NULL; + map->sdata = NULL; + map->fixup_tail = &map->fixup; + map->sdata_tail = &map->sdata; return 0; } static void ucimap_add_alloc(struct ucimap_section_data *sd, void *ptr) { - struct uci_alloc *a = &sd->allocmap[sd->allocmap_len++]; + struct ucimap_alloc *a = &sd->allocmap[sd->allocmap_len++]; a->ptr = ptr; } @@ -141,8 +147,8 @@ ucimap_free_section(struct uci_map *map, struct ucimap_section_data *sd) int i; section = ucimap_section_ptr(sd); - if (!list_empty(&sd->list)) - list_del(&sd->list); + if (sd->ref) + *sd->ref = sd->next; if (sd->sm->free) sd->sm->free(map, section); @@ -153,7 +159,7 @@ ucimap_free_section(struct uci_map *map, struct ucimap_section_data *sd) if (sd->alloc_custom) { for (i = 0; i < sd->alloc_custom_len; i++) { - struct uci_alloc_custom *a = &sd->alloc_custom[i]; + struct ucimap_alloc_custom *a = &sd->alloc_custom[i]; a->om->free(a->section, a->om, a->ptr); } free(sd->alloc_custom); @@ -166,30 +172,26 @@ ucimap_free_section(struct uci_map *map, struct ucimap_section_data *sd) void ucimap_cleanup(struct uci_map *map) { - struct list_head *ptr, *tmp; + struct ucimap_section_data *sd; - list_for_each_safe(ptr, tmp, &map->sdata) { - struct ucimap_section_data *sd = list_entry(ptr, struct ucimap_section_data, list); + for (sd = map->sdata; sd; sd = sd->next) { ucimap_free_section(map, sd); } } static void * -ucimap_find_section(struct uci_map *map, struct uci_fixup *f) +ucimap_find_section(struct uci_map *map, struct ucimap_fixup *f) { struct ucimap_section_data *sd; - struct list_head *p; - list_for_each(p, &map->sdata) { - sd = list_entry(p, struct ucimap_section_data, list); + for (sd = map->sdata; sd; sd = sd->next) { if (sd->sm != f->sm) continue; if (strcmp(f->name, sd->section_name) != 0) continue; return ucimap_section_ptr(sd); } - list_for_each(p, &map->pending) { - sd = list_entry(p, struct ucimap_section_data, list); + for (sd = map->pending; sd; sd = sd->next) { if (sd->sm != f->sm) continue; if (strcmp(f->name, sd->section_name) != 0) @@ -200,7 +202,7 @@ ucimap_find_section(struct uci_map *map, struct uci_fixup *f) } static bool -ucimap_handle_fixup(struct uci_map *map, struct uci_fixup *f) +ucimap_handle_fixup(struct uci_map *map, struct ucimap_fixup *f) { void *ptr = ucimap_find_section(map, f); struct ucimap_list *list; @@ -223,8 +225,8 @@ ucimap_handle_fixup(struct uci_map *map, struct uci_fixup *f) void ucimap_free_item(struct ucimap_section_data *sd, void *item) { - struct uci_alloc_custom *ac; - struct uci_alloc *a; + struct ucimap_alloc_custom *ac; + struct ucimap_alloc *a; void *ptr = *((void **) item); int i; @@ -249,7 +251,7 @@ ucimap_free_item(struct ucimap_section_data *sd, void *item) if (i != sd->alloc_custom_len - 1) memcpy(ac, &sd->alloc_custom[sd->alloc_custom_len - 1], - sizeof(struct uci_alloc_custom)); + sizeof(struct ucimap_alloc_custom)); ac->om->free(ac->section, ac->om, ac->ptr); sd->alloc_custom_len--; @@ -261,7 +263,7 @@ int ucimap_resize_list(struct ucimap_section_data *sd, struct ucimap_list **list, int items) { struct ucimap_list *new; - struct uci_alloc *a; + struct ucimap_alloc *a; int i, offset = 0; int size = sizeof(struct ucimap_list) + items * sizeof(union ucimap_data); @@ -298,10 +300,9 @@ set: static void ucimap_add_fixup(struct ucimap_section_data *sd, union ucimap_data *data, struct uci_optmap *om, const char *str) { - struct uci_fixup *f, tmp; + struct ucimap_fixup *f, tmp; struct uci_map *map = sd->map; - INIT_LIST_HEAD(&tmp.list); tmp.sm = om->data.sm; tmp.name = str; tmp.type = om->type; @@ -309,18 +310,20 @@ ucimap_add_fixup(struct ucimap_section_data *sd, union ucimap_data *data, struct if (ucimap_handle_fixup(map, &tmp)) return; - f = malloc(sizeof(struct uci_fixup)); + f = malloc(sizeof(struct ucimap_fixup)); if (!f) return; memcpy(f, &tmp, sizeof(tmp)); - list_add_tail(&f->list, &map->fixup); + f->next = NULL; + *map->fixup_tail = f; + map->fixup_tail = &f->next; } static void ucimap_add_custom_alloc(struct ucimap_section_data *sd, struct uci_optmap *om, void *ptr) { - struct uci_alloc_custom *a = &sd->alloc_custom[sd->alloc_custom_len++]; + struct ucimap_alloc_custom *a = &sd->alloc_custom[sd->alloc_custom_len++]; a->section = ucimap_section_ptr(sd); a->om = om; @@ -471,15 +474,24 @@ ucimap_parse_options(struct uci_map *map, struct uci_sectionmap *sm, struct ucim return 0; } +static void +ucimap_add_section_list(struct uci_map *map, struct ucimap_section_data *sd) +{ + sd->ref = map->sdata_tail; + *sd->ref = sd; + map->sdata_tail = &sd->next; +} + static void ucimap_add_section(struct ucimap_section_data *sd) { struct uci_map *map = sd->map; + sd->next = NULL; if (sd->sm->add(map, ucimap_section_ptr(sd)) < 0) ucimap_free_section(map, sd); else - list_add_tail(&sd->list, &map->sdata); + ucimap_add_section_list(map, sd); } #ifdef UCI_DEBUG @@ -579,7 +591,6 @@ ucimap_parse_section(struct uci_map *map, struct uci_sectionmap *sm, struct ucim int n_alloc_custom = 0; int err; - INIT_LIST_HEAD(&sd->list); sd->map = map; sd->sm = sm; @@ -646,12 +657,12 @@ ucimap_parse_section(struct uci_map *map, struct uci_sectionmap *sm, struct ucim } } - sd->allocmap = calloc(n_alloc, sizeof(struct uci_alloc)); + sd->allocmap = calloc(n_alloc, sizeof(struct ucimap_alloc)); if (!sd->allocmap) goto error_mem; if (n_alloc_custom > 0) { - sd->alloc_custom = calloc(n_alloc_custom, sizeof(struct uci_alloc_custom)); + sd->alloc_custom = calloc(n_alloc_custom, sizeof(struct ucimap_alloc_custom)); if (!sd->alloc_custom) goto error_mem; } @@ -683,7 +694,7 @@ ucimap_parse_section(struct uci_map *map, struct uci_sectionmap *sm, struct ucim if (map->parsed) { ucimap_add_section(sd); } else { - list_add_tail(&sd->list, &map->pending); + ucimap_add_section_list(map, sd); } err = ucimap_parse_options(map, sm, sd, s); @@ -853,10 +864,13 @@ void ucimap_parse(struct uci_map *map, struct uci_package *pkg) { struct uci_element *e; - struct list_head *p, *tmp; + struct ucimap_section_data *sd, **sd_tail; + struct ucimap_fixup *f; int i; - INIT_LIST_HEAD(&map->fixup); + sd_tail = map->sdata_tail; + map->parsed = false; + map->sdata_tail = &map->pending; uci_foreach_element(&pkg->sections, e) { struct uci_section *s = uci_to_section(e); @@ -880,20 +894,26 @@ ucimap_parse(struct uci_map *map, struct uci_package *pkg) ucimap_parse_section(map, sm, sd, s); } } - map->parsed = true; + if (!map->parsed) { + map->parsed = true; + map->sdata_tail = sd_tail; + } - list_for_each_safe(p, tmp, &map->fixup) { - struct uci_fixup *f = list_entry(p, struct uci_fixup, list); + f = map->fixup; + while (f) { + struct ucimap_fixup *next = f->next; ucimap_handle_fixup(map, f); - list_del(&f->list); free(f); + f = next; } + map->fixup_tail = &map->fixup; + map->fixup = NULL; - list_for_each_safe(p, tmp, &map->pending) { - struct ucimap_section_data *sd; - sd = list_entry(p, struct ucimap_section_data, list); - - list_del_init(&sd->list); + sd = map->pending; + while (sd) { + struct ucimap_section_data *next = sd->next; ucimap_add_section(sd); + sd = next; } + map->pending = NULL; }