Browse Source

add parser helpers similar to the blobmsg parser in libubox

Felix Fietkau 13 years ago
parent
commit
862b173154
3 changed files with 155 additions and 1 deletions
  1. 1 1
      CMakeLists.txt
  2. 130 0
      parse.c
  3. 24 0
      uci.h

+ 1 - 1
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)

+ 130 - 0
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;
+}
+
+

+ 24 - 0
uci.h

@@ -33,6 +33,7 @@ extern "C" {
 #include <stdbool.h>
 #include <setjmp.h>
 #include <stdio.h>
+#include <stdint.h>
 
 #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