LIBUCI_DEPS=file.c history.c list.c util.c uci.h uci_config.h uci_internal.h
-all: uci-static uci libuci.$(SHLIB_EXT) ucimap-example
+all: uci libuci.$(SHLIB_EXT) uci-static ucimap-example
cli.o: cli.c uci.h uci_config.h
-ucimap.o: ucimap.c uci.h uci_config.h ucimap.h uci_list.h
+ucimap.o: ucimap.c uci.h uci_config.h ucimap.h
uci_config.h: FORCE
@rm -f "$@.tmp"
rm -f "$@.tmp"; \
fi
+%.o: %.c
+ $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $<
+
+%-shared.o: %.c
+ $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(FPIC) $<
+
+%-static.o: %.c
+ $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $<
+
uci: cli.o libuci.$(SHLIB_EXT)
$(CC) -o $@ $< -L. -luci $(LIBS)
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
libuci-static.o: libuci.c $(LIBUCI_DEPS)
- $(CC) $(CFLAGS) -c -o $@ $<
-
libuci-shared.o: libuci.c $(LIBUCI_DEPS)
- $(CC) $(CFLAGS) $(FPIC) -c -o $@ $<
-
ucimap-static.o: ucimap.c $(LIBUCI_DEPS) ucimap.h
- $(CC) $(CFLAGS) -c -o $@ $<
-
ucimap-shared.o: ucimap.c $(LIBUCI_DEPS) ucimap.h
- $(CC) $(CFLAGS) $(FPIC) -c -o $@ $<
libuci.a: libuci-static.o ucimap-static.o
rm -f $@
$(LINK) $(SHLIB_FLAGS) -o $(SHLIB_FILE) $^ $(LIBS)
ln -sf $(SHLIB_FILE) $@
-ucimap-example: ucimap-example.c libuci.a
- $(CC) $(CFLAGS) -I. -o $@ $^ $(LIBS)
+ucimap-example.o: ucimap-example.c list.h
+ucimap-example: ucimap-example.o libuci.a
+ $(CC) $(CFLAGS) -o $@ $^ $(LIBS)
clean:
rm -f uci uci-static *.[oa] *.so* *.dylib* uci_config.h ucimap-example
$(MKDIR) -p $(DESTDIR)$(prefix)/lib
$(MKDIR) -p $(DESTDIR)$(prefix)/include
$(INSTALL) -m0644 libuci.a $(DESTDIR)$(prefix)/lib/
- $(INSTALL) -m0644 uci_config.h uci.h uci_list.h ucimap.h $(DESTDIR)$(prefix)/include/
+ $(INSTALL) -m0644 uci_config.h uci.h ucimap.h $(DESTDIR)$(prefix)/include/
install-bin: all
$(MKDIR) -p $(DESTDIR)$(prefix)/lib
/*
- * ucimap - library for mapping uci sections into data structures
- * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ * ucimap.c - Library for the Unified Configuration Interface
+ * Copyright (C) 2008-2009 Felix Fietkau <nbd@openwrt.org>
*
* 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,
* 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 <strings.h>
#include <stdbool.h>
#include <string.h>
#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;
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;
}
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);
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);
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)
}
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;
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;
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--;
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);
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;
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;
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
int n_alloc_custom = 0;
int err;
- INIT_LIST_HEAD(&sd->list);
sd->map = map;
sd->sm = sm;
}
}
- 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;
}
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);
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);
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;
}
/*
- * ucimap - library for mapping uci sections into data structures
- * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
+ * ucimap.h - Library for the Unified Configuration Interface
+ * Copyright (C) 2008-2009 Felix Fietkau <nbd@openwrt.org>
*
* 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,
* 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
+ */
+
#ifndef __UCIMAP_H
#define __UCIMAP_H
#include <stdbool.h>
-#include "uci_list.h"
#include "uci.h"
#ifndef ARRAY_SIZE
struct uci_sectionmap;
struct uci_optmap;
+
struct ucimap_list;
-struct uci_alloc;
-struct uci_alloc_custom;
+struct ucimap_fixup;
+struct ucimap_alloc;
+struct ucimap_alloc_custom;
+struct ucimap_section_data;
struct uci_map {
struct uci_sectionmap **sections;
unsigned int n_sections;
- struct list_head sdata;
- struct list_head fixup;
- struct list_head pending;
bool parsed;
-
- void *priv; /* user data */
+ void *priv;
+
+ /* private */
+ struct ucimap_fixup *fixup;
+ struct ucimap_fixup **fixup_tail;
+ struct ucimap_section_data *sdata;
+ struct ucimap_section_data *pending;
+ struct ucimap_section_data **sdata_tail;
};
enum ucimap_type {
};
struct ucimap_section_data {
- struct list_head list;
struct uci_map *map;
struct uci_sectionmap *sm;
const char *section_name;
- /* list of allocations done by ucimap */
- struct uci_alloc *allocmap;
- struct uci_alloc_custom *alloc_custom;
- unsigned int allocmap_len;
- unsigned int alloc_custom_len;
-
/* map for changed fields */
unsigned char *cmap;
bool done;
+
+ /* internal */
+ struct ucimap_section_data *next, **ref;
+ struct ucimap_alloc *allocmap;
+ struct ucimap_alloc_custom *alloc_custom;
+ unsigned int allocmap_len;
+ unsigned int alloc_custom_len;
};
struct uci_sectionmap {