tests: remove straying echo in 020_get.
[project/uci.git] / parse.c
1 /*
2  * libuci - Library for the Unified Configuration Interface
3  * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License version 2.1
7  * as published by the Free Software Foundation
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU Lesser General Public License for more details.
13  */
14
15 #include <string.h>
16 #include <stdint.h>
17
18 #include "uci.h"
19
20 void uci_parse_section(struct uci_section *s, const struct uci_parse_option *opts,
21                        int n_opts, struct uci_option **tb)
22 {
23         struct uci_element *e;
24
25         memset(tb, 0, n_opts * sizeof(*tb));
26
27         uci_foreach_element(&s->options, e) {
28                 struct uci_option *o = uci_to_option(e);
29                 int i;
30
31                 for (i = 0; i < n_opts; i++) {
32                         if (tb[i])
33                                 continue;
34
35                         if (strcmp(opts[i].name, o->e.name) != 0)
36                                 continue;
37
38                         if (opts[i].type != o->type)
39                                 continue;
40
41                         /* match found */
42                         tb[i] = o;
43                         break;
44                 }
45         }
46 }
47
48 //-----------------------------------------------------------------------------
49 // MurmurHashNeutral2, by Austin Appleby
50
51 // Same as MurmurHash2, but endian- and alignment-neutral.
52 static uint32_t hash_murmur2(uint32_t h, const void * key, int len)
53 {
54         const unsigned char * data = key;
55         const uint32_t m = 0x5bd1e995;
56         const int r = 24;
57
58         while(len >= 4)
59         {
60                 unsigned int k;
61
62                 k  = data[0];
63                 k |= data[1] << 8;
64                 k |= data[2] << 16;
65                 k |= data[3] << 24;
66
67                 k *= m;
68                 k ^= k >> r;
69                 k *= m;
70
71                 h *= m;
72                 h ^= k;
73
74                 data += 4;
75                 len -= 4;
76         }
77
78         switch(len)
79         {
80         case 3: h ^= data[2] << 16;
81         case 2: h ^= data[1] << 8;
82         case 1: h ^= data[0];
83                 h *= m;
84         };
85
86         h ^= h >> 13;
87         h *= m;
88         h ^= h >> 15;
89
90         return h;
91 }
92
93 static uint32_t uci_hash_list(uint32_t h, const struct uci_list *list)
94 {
95         const struct uci_element *e;
96
97         uci_foreach_element(list, e) {
98                 h = hash_murmur2(h, e->name, strlen(e->name) + 1);
99         }
100         return h;
101 }
102
103 uint32_t uci_hash_options(struct uci_option **tb, int n_opts)
104 {
105         uint32_t h = 0xdeadc0de;
106         int i;
107
108         for (i = 0; i < n_opts; i++) {
109                 const struct uci_option *o = tb[i];
110
111                 if (!tb[i])
112                         continue;
113
114                 h = hash_murmur2(h, o->e.name, strlen(o->e.name) + 1);
115                 h = hash_murmur2(h, &o->type, sizeof(o->type));
116
117                 switch (tb[i]->type) {
118                 case UCI_TYPE_STRING:
119                         h = hash_murmur2(h, o->v.string, strlen(o->v.string) + 1);
120                         break;
121                 case UCI_TYPE_LIST:
122                         h = uci_hash_list(h, &o->v.list);
123                         break;
124                 }
125         }
126
127         return h;
128 }
129
130