-
Notifications
You must be signed in to change notification settings - Fork 0
/
parse.c
130 lines (101 loc) · 2.53 KB
/
parse.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
* 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 Lesser General Public License for more details.
*/
#include <string.h>
#include <stdint.h>
#include "uci.h"
void uci_parse_section(struct uci_section *s, const 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 != 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, const struct uci_list *list)
{
const 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++) {
const 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;
}