BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file NCDMethodIndex.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29  
30 #include <string.h>
31 #include <stdlib.h>
32 #include <limits.h>
33  
34 #include <misc/hashfun.h>
35 #include <misc/balloc.h>
36 #include <misc/strdup.h>
37  
38 #include "NCDMethodIndex.h"
39  
40 #include "NCDMethodIndex_hash.h"
41 #include <structure/CHash_impl.h>
42  
43 #define GROWARRAY_NAME NamesArray
44 #define GROWARRAY_OBJECT_TYPE NCDMethodIndex
45 #define GROWARRAY_ARRAY_MEMBER names
46 #define GROWARRAY_CAPACITY_MEMBER names_capacity
47 #define GROWARRAY_MAX_CAPACITY INT_MAX
48 #include <misc/grow_array.h>
49  
50 #define GROWARRAY_NAME EntriesArray
51 #define GROWARRAY_OBJECT_TYPE NCDMethodIndex
52 #define GROWARRAY_ARRAY_MEMBER entries
53 #define GROWARRAY_CAPACITY_MEMBER entries_capacity
54 #define GROWARRAY_MAX_CAPACITY INT_MAX
55 #include <misc/grow_array.h>
56  
57 #include <generated/blog_channel_ncd.h>
58  
59 static int find_method_name (NCDMethodIndex *o, const char *method_name, int *out_entry_idx)
60 {
61 ASSERT(method_name)
62  
63 NCDMethodIndex__HashRef ref = NCDMethodIndex__Hash_Lookup(&o->hash, o->names, method_name);
64 if (ref.link == -1) {
65 return 0;
66 }
67  
68 ASSERT(ref.link >= 0)
69 ASSERT(ref.link < o->num_names)
70  
71 struct NCDMethodIndex__method_name *name_entry = ref.ptr;
72 ASSERT(!strcmp(name_entry->method_name, method_name))
73 ASSERT(name_entry->first_entry >= 0)
74 ASSERT(name_entry->first_entry < o->num_entries)
75  
76 if (out_entry_idx) {
77 *out_entry_idx = name_entry->first_entry;
78 }
79 return 1;
80 }
81  
82 static int add_method_name (NCDMethodIndex *o, const char *method_name, int *out_entry_idx)
83 {
84 ASSERT(method_name)
85 ASSERT(!find_method_name(o, method_name, NULL))
86  
87 if (o->num_entries == o->entries_capacity && !EntriesArray_DoubleUp(o)) {
88 BLog(BLOG_ERROR, "EntriesArray_DoubleUp failed");
89 goto fail0;
90 }
91  
92 if (o->num_names == o->names_capacity && !NamesArray_DoubleUp(o)) {
93 BLog(BLOG_ERROR, "NamesArray_DoubleUp failed");
94 goto fail0;
95 }
96  
97 struct NCDMethodIndex__entry *entry = &o->entries[o->num_entries];
98 entry->obj_type = -1;
99 entry->next = -1;
100  
101 struct NCDMethodIndex__method_name *name_entry = &o->names[o->num_names];
102  
103 if (!(name_entry->method_name = b_strdup(method_name))) {
104 BLog(BLOG_ERROR, "b_strdup failed");
105 goto fail0;
106 }
107  
108 name_entry->first_entry = o->num_entries;
109  
110 NCDMethodIndex__HashRef ref = {name_entry, o->num_names};
111 int res = NCDMethodIndex__Hash_Insert(&o->hash, o->names, ref, NULL);
112 ASSERT_EXECUTE(res)
113  
114 o->num_entries++;
115 o->num_names++;
116  
117 if (out_entry_idx) {
118 *out_entry_idx = name_entry->first_entry;
119 }
120 return 1;
121  
122 fail0:
123 return 0;
124 }
125  
126 int NCDMethodIndex_Init (NCDMethodIndex *o, NCDStringIndex *string_index)
127 {
128 ASSERT(string_index)
129  
130 o->string_index = string_index;
131  
132 if (!NamesArray_Init(o, NCDMETHODINDEX_NUM_EXPECTED_METHOD_NAMES)) {
133 BLog(BLOG_ERROR, "NamesArray_Init failed");
134 goto fail0;
135 }
136  
137 if (!EntriesArray_Init(o, NCDMETHODINDEX_NUM_EXPECTED_ENTRIES)) {
138 BLog(BLOG_ERROR, "EntriesArray_Init failed");
139 goto fail1;
140 }
141  
142 o->num_names = 0;
143 o->num_entries = 0;
144  
145 if (!NCDMethodIndex__Hash_Init(&o->hash, NCDMETHODINDEX_NUM_EXPECTED_METHOD_NAMES)) {
146 BLog(BLOG_ERROR, "NCDMethodIndex__Hash_Init failed");
147 goto fail2;
148 }
149  
150 return 1;
151  
152 fail2:
153 EntriesArray_Free(o);
154 fail1:
155 NamesArray_Free(o);
156 fail0:
157 return 0;
158 }
159  
160 void NCDMethodIndex_Free (NCDMethodIndex *o)
161 {
162 for (int i = 0; i < o->num_names; i++) {
163 free(o->names[i].method_name);
164 }
165  
166 NCDMethodIndex__Hash_Free(&o->hash);
167 EntriesArray_Free(o);
168 NamesArray_Free(o);
169 }
170  
171 int NCDMethodIndex_AddMethod (NCDMethodIndex *o, const char *obj_type, size_t obj_type_len, const char *method_name, const struct NCDInterpModule *module)
172 {
173 ASSERT(obj_type)
174 ASSERT(method_name)
175 ASSERT(module)
176  
177 NCD_string_id_t obj_type_id = NCDStringIndex_GetBin(o->string_index, obj_type, obj_type_len);
178 if (obj_type_id < 0) {
179 BLog(BLOG_ERROR, "NCDStringIndex_Get failed");
180 goto fail0;
181 }
182  
183 int entry_idx;
184 int first_entry_idx;
185  
186 if (!find_method_name(o, method_name, &first_entry_idx)) {
187 if (!add_method_name(o, method_name, &entry_idx)) {
188 goto fail0;
189 }
190  
191 ASSERT(entry_idx >= 0)
192 ASSERT(entry_idx < o->num_entries)
193  
194 struct NCDMethodIndex__entry *entry = &o->entries[entry_idx];
195  
196 entry->obj_type = obj_type_id;
197 entry->module = module;
198 } else {
199 ASSERT(first_entry_idx >= 0)
200 ASSERT(first_entry_idx < o->num_entries)
201  
202 if (o->num_entries == o->entries_capacity && !EntriesArray_DoubleUp(o)) {
203 BLog(BLOG_ERROR, "EntriesArray_DoubleUp failed");
204 goto fail0;
205 }
206  
207 entry_idx = o->num_entries;
208 struct NCDMethodIndex__entry *entry = &o->entries[o->num_entries];
209  
210 entry->obj_type = obj_type_id;
211 entry->module = module;
212  
213 entry->next = o->entries[first_entry_idx].next;
214 o->entries[first_entry_idx].next = o->num_entries;
215  
216 o->num_entries++;
217 }
218  
219 return entry_idx;
220  
221 fail0:
222 return -1;
223 }
224  
225 void NCDMethodIndex_RemoveMethod (NCDMethodIndex *o, int method_name_id)
226 {
227 ASSERT(method_name_id >= 0)
228 ASSERT(method_name_id < o->num_entries)
229 ASSERT(o->entries[method_name_id].obj_type >= 0)
230  
231 o->entries[method_name_id].obj_type = -1;
232 }
233  
234 int NCDMethodIndex_GetMethodNameId (NCDMethodIndex *o, const char *method_name)
235 {
236 ASSERT(method_name)
237  
238 int first_entry_idx;
239  
240 if (!find_method_name(o, method_name, &first_entry_idx)) {
241 if (!add_method_name(o, method_name, &first_entry_idx)) {
242 return -1;
243 }
244 }
245  
246 ASSERT(first_entry_idx >= 0)
247 ASSERT(first_entry_idx < o->num_entries)
248  
249 return first_entry_idx;
250 }
251  
252 const struct NCDInterpModule * NCDMethodIndex_GetMethodModule (NCDMethodIndex *o, NCD_string_id_t obj_type, int method_name_id)
253 {
254 ASSERT(obj_type >= 0)
255 ASSERT(method_name_id >= 0)
256 ASSERT(method_name_id < o->num_entries)
257  
258 do {
259 struct NCDMethodIndex__entry *entry = &o->entries[method_name_id];
260  
261 if (entry->obj_type == obj_type) {
262 ASSERT(entry->module)
263 return entry->module;
264 }
265  
266 method_name_id = entry->next;
267 ASSERT(method_name_id >= -1)
268 ASSERT(method_name_id < o->num_entries)
269 } while (method_name_id >= 0);
270  
271 return NULL;
272 }