From 862b173154812f4efe5ad198604106826422b508 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 5 Apr 2011 03:29:17 +0200 Subject: [PATCH] add parser helpers similar to the blobmsg parser in libubox --- CMakeLists.txt | 2 +- parse.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++ uci.h | 24 +++++++++ 3 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 parse.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 7df3be9..54c5cf2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ OPTION(BUILD_LUA "build Lua plugin" ON) CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/uci_config.h.in ${CMAKE_SOURCE_DIR}/uci_config.h ) -SET(LIB_SOURCES libuci.c file.c util.c delta.c) +SET(LIB_SOURCES libuci.c file.c util.c delta.c parse.c) ADD_LIBRARY(uci-shared SHARED ${LIB_SOURCES}) SET_TARGET_PROPERTIES(uci-shared PROPERTIES OUTPUT_NAME uci) diff --git a/parse.c b/parse.c new file mode 100644 index 0000000..d0684f9 --- /dev/null +++ b/parse.c @@ -0,0 +1,130 @@ +/* + * libuci - Library for the Unified Configuration Interface + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * 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, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "uci.h" + +void uci_parse_section(struct uci_section *s, struct uci_parse_option *opts, + int n_opts, struct uci_option **tb) +{ + struct uci_element *e; + + memset(tb, 0, n_opts * sizeof(*tb)); + + uci_foreach_element(&s->options, e) { + struct uci_option *o = uci_to_option(e); + int i; + + for (i = 0; i < n_opts; i++) { + if (tb[i]) + continue; + + if (strcmp(opts[i].name, o->e.name) != 0) + continue; + + if (opts[i].type >= 0 && opts[i].type != o->type) + continue; + + /* match found */ + tb[i] = o; + break; + } + } +} + +//----------------------------------------------------------------------------- +// MurmurHashNeutral2, by Austin Appleby + +// Same as MurmurHash2, but endian- and alignment-neutral. +static uint32_t hash_murmur2(uint32_t h, const void * key, int len) +{ + const unsigned char * data = key; + const uint32_t m = 0x5bd1e995; + const int r = 24; + + while(len >= 4) + { + unsigned int k; + + k = data[0]; + k |= data[1] << 8; + k |= data[2] << 16; + k |= data[3] << 24; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + data += 4; + len -= 4; + } + + switch(len) + { + case 3: h ^= data[2] << 16; + case 2: h ^= data[1] << 8; + case 1: h ^= data[0]; + h *= m; + }; + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return h; +} + +static uint32_t uci_hash_list(uint32_t h, struct uci_list *list) +{ + struct uci_element *e; + + uci_foreach_element(list, e) { + h = hash_murmur2(h, e->name, strlen(e->name) + 1); + } + return h; +} + +uint32_t uci_hash_options(struct uci_option **tb, int n_opts) +{ + uint32_t h = 0xdeadc0de; + int i; + + for (i = 0; i < n_opts; i++) { + struct uci_option *o = tb[i]; + + if (!tb[i]) + continue; + + h = hash_murmur2(h, o->e.name, strlen(o->e.name) + 1); + h = hash_murmur2(h, &o->type, sizeof(o->type)); + + switch (tb[i]->type) { + case UCI_TYPE_STRING: + h = hash_murmur2(h, o->v.string, strlen(o->v.string) + 1); + break; + case UCI_TYPE_LIST: + h = uci_hash_list(h, &o->v.list); + break; + } + } + + return h; +} + + diff --git a/uci.h b/uci.h index 97bff7d..696f4f6 100644 --- a/uci.h +++ b/uci.h @@ -33,6 +33,7 @@ extern "C" { #include #include #include +#include #define UCI_CONFDIR "/etc/config" #define UCI_SAVEDIR "/tmp/.uci" @@ -69,6 +70,7 @@ struct uci_option; struct uci_delta; struct uci_context; struct uci_backend; +struct uci_parse_option; struct uci_parse_context; @@ -348,6 +350,23 @@ int uci_parse_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str); */ int uci_lookup_next(struct uci_context *ctx, struct uci_element **e, struct uci_list *list, const char *name); +/** + * uci_parse_section: look up a set of options + * @s: uci section + * @opts: list of options to look up + * @n_opts: number of options to look up + * @tb: array of pointers to found options + */ +void uci_parse_section(struct uci_section *s, struct uci_parse_option *opts, + int n_opts, struct uci_option **tb); + +/** + * uci_hash_options: build a hash over a list of options + * @tb: list of option pointers + * @n_opts: number of options + */ +uint32_t uci_hash_options(struct uci_option **tb, int n_opts); + /* UCI data structures */ enum uci_type { @@ -525,6 +544,11 @@ struct uci_plugin void *dlh; }; +struct uci_parse_option { + const char *name; + enum uci_option_type type; +}; + /* linked list handling */ #ifndef offsetof -- 2.30.2