summaryrefslogtreecommitdiff
path: root/parse.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2011-04-05 03:29:17 +0200
committerFelix Fietkau <nbd@openwrt.org>2011-04-05 03:29:21 +0200
commit862b173154812f4efe5ad198604106826422b508 (patch)
tree31d5f48031b1de94615a5d342f229c0c9672fa00 /parse.c
parent14bdf8689990afdb5fd8caaf448e9c7d2c0d9c99 (diff)
downloaduci-862b173154812f4efe5ad198604106826422b508.tar.gz
add parser helpers similar to the blobmsg parser in libubox
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c130
1 files changed, 130 insertions, 0 deletions
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 <nbd@openwrt.org>
+ *
+ * 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 <string.h>
+#include <stdint.h>
+
+#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;
+}
+
+