aboutsummaryrefslogtreecommitdiff
path: root/src/regex/regex_test_lib.c
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2012-12-17 12:35:19 +0000
committerBart Polot <bart@net.in.tum.de>2012-12-17 12:35:19 +0000
commit11cc044427e734c83af65ee340dd10ec70c97b1c (patch)
tree2c807dc234644519ff2f341cf6ca2f1cb2a084f2 /src/regex/regex_test_lib.c
parent07ce0aaf09b4bcdf37b1524a9a497d4a185aba91 (diff)
downloadgnunet-11cc044427e734c83af65ee340dd10ec70c97b1c.tar.gz
gnunet-11cc044427e734c83af65ee340dd10ec70c97b1c.zip
- move regex_from_file and combine to separate lib file
Diffstat (limited to 'src/regex/regex_test_lib.c')
-rw-r--r--src/regex/regex_test_lib.c248
1 files changed, 248 insertions, 0 deletions
diff --git a/src/regex/regex_test_lib.c b/src/regex/regex_test_lib.c
new file mode 100644
index 000000000..d02afa942
--- /dev/null
+++ b/src/regex/regex_test_lib.c
@@ -0,0 +1,248 @@
1/*
2 * This file is part of GNUnet
3 * (C) 2012 Christian Grothoff (and other contributing authors)
4 *
5 * GNUnet is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 3, or (at your
8 * option) any later version.
9 *
10 * GNUnet is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with GNUnet; see the file COPYING. If not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 */
20/**
21 * @file src/regex/regex_test_lib.c
22 * @brief library to read regexes representing IP networks from a file.
23 * and simplyfinying the into one big regex, in order to run
24 * tests (regex performance, mesh profiler).
25 * @author Bartlomiej Polot
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30
31struct RegexCombineCtx {
32 struct RegexCombineCtx *next;
33 struct RegexCombineCtx *prev;
34
35 struct RegexCombineCtx *head;
36 struct RegexCombineCtx *tail;
37
38 char *s;
39};
40
41
42static char *
43regex_combine (struct RegexCombineCtx *ctx)
44{
45 struct RegexCombineCtx *p;
46 size_t len;
47 char *regex;
48 char *tmp;
49 char *s;
50
51 if (NULL != ctx->s)
52 GNUNET_asprintf (&regex, "%s(", ctx->s);
53 else
54 regex = GNUNET_strdup ("(");
55 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "prefix: %s\n", regex);
56
57 for (p = ctx->head; NULL != p; p = p->next)
58 {
59 s = regex_combine (p);
60 GNUNET_asprintf (&tmp, "%s%s|", regex, s);
61 GNUNET_free_non_null (s);
62 GNUNET_free_non_null (regex);
63 regex = tmp;
64 }
65 len = strlen (regex);
66 if (1 == len)
67 return GNUNET_strdup ("");
68
69 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pre-partial: %s\n", regex);
70 if ('|' == regex[len - 1])
71 regex[len - 1] = ')';
72 if ('(' == regex[len - 1])
73 regex[len - 1] = '\0';
74
75 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "partial: %s\n", regex);
76 return regex;
77}
78
79static void
80regex_add (struct RegexCombineCtx *ctx, const char *regex)
81{
82 struct RegexCombineCtx *p;
83 const char *rest;
84
85 rest = &regex[1];
86 for (p = ctx->head; NULL != p; p = p->next)
87 {
88 if (p->s[0] == regex[0])
89 {
90 if (1 == strlen(p->s))
91 {
92 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "common char %s\n", p->s);
93 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding %s\n", rest);
94 regex_add (p, rest);
95 }
96 else
97 {
98 struct RegexCombineCtx *new;
99 new = GNUNET_malloc (sizeof (struct RegexCombineCtx));
100 new->s = GNUNET_strdup (&p->s[1]);
101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " p has now %s\n", p->s);
102 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " p will have %.1s\n", p->s);
103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regex is %s\n", regex);
104 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " new has now %s\n", new->s);
105 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " rest is now %s\n", rest);
106 p->s[1] = '\0'; /* dont realloc */
107 GNUNET_CONTAINER_DLL_insert (p->head, p->tail, new);
108 regex_add (p, rest);
109 }
110 return;
111 }
112 }
113 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " no match\n");
114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " new state %s\n", regex);
115 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " under %s\n", ctx->s);
116 p = GNUNET_malloc (sizeof (struct RegexCombineCtx));
117 p->s = GNUNET_strdup (regex);
118 GNUNET_CONTAINER_DLL_insert (ctx->head, ctx->tail, p);
119}
120
121
122/**
123 * Return a prefix-combine regex that matches the same strings as
124 * any of the original regexes.
125 *
126 * WARNING: only useful for reading specific regexes for specific applications,
127 * namely the gnunet-regex-profiler / gnunet-regex-daemon.
128 * This function DOES NOT support arbitrary regex combining.
129 */
130char *
131GNUNET_REGEX_combine (char * const regexes[])
132{
133 unsigned int i;
134 char *combined;
135 const char *current;
136 struct RegexCombineCtx ctx;
137
138 memset (&ctx, 0, sizeof (struct RegexCombineCtx));
139 for (i = 0; regexes[i]; i++)
140 {
141 current = regexes[i];
142 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Regex %u: %s\n", i, current);
143 regex_add (&ctx, current);
144 }
145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\nCombining...\n");
146
147 combined = regex_combine (&ctx);
148
149 return combined;
150}
151
152
153/**
154 * Read a set of regexes from a file, one per line and return them in an array
155 * suitable for GNUNET_REGEX_combine.
156 * The array must be free'd using GNUNET_REGEX_free_from_file.
157 *
158 * @param filename Name of the file containing the regexes.
159 *
160 * @return A newly allocated, NULL terminated array of regexes.
161 */
162char **
163GNUNET_REGEX_read_from_file (const char *filename)
164{
165 struct GNUNET_DISK_FileHandle *f;
166 unsigned int nr;
167 unsigned int offset;
168 off_t size;
169 size_t len;
170 char *buffer;
171 char *regex;
172 char **regexes;
173
174 f = GNUNET_DISK_file_open (filename,
175 GNUNET_DISK_OPEN_READ,
176 GNUNET_DISK_PERM_NONE);
177 if (NULL == f)
178 {
179 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
180 "Can't open file %s for reading\n", filename);
181 return NULL;
182 }
183 if (GNUNET_OK != GNUNET_DISK_file_handle_size (f, &size))
184 {
185 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
186 "Can't get size of file %s\n", filename);
187 return NULL;
188 }
189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
190 "using file %s, size %llu\n",
191 filename, (unsigned long long) size);
192
193 buffer = GNUNET_malloc (size + 1);
194 GNUNET_DISK_file_read (f, buffer, size);
195 GNUNET_DISK_file_close (f);
196 regexes = GNUNET_malloc (sizeof (char *));
197 nr = 1;
198 offset = 0;
199 regex = NULL;
200 do
201 {
202 if (NULL == regex)
203 regex = GNUNET_malloc (size + 1);
204 len = (size_t) sscanf (&buffer[offset], "%s", regex);
205 if (0 == len)
206 break;
207 len = strlen (regex);
208 offset += len + 1;
209 if (len < 1)
210 continue;
211 if (len < 6 || strncmp (&regex[len - 6], "(0|1)*", 6) != 0)
212 {
213 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
214 "%s (line %u) does not end in \"(0|1)*\"\n",
215 buffer, nr);
216 }
217 else
218 {
219 len -= 6;
220 buffer[len] = '\0';
221 }
222 regex = GNUNET_realloc (regex, len + 1);
223 GNUNET_array_grow (regexes, nr, nr + 1);
224 regexes[nr - 2] = regex;
225 regexes[nr - 1] = NULL;
226 } while (offset < size);
227 GNUNET_free (buffer);
228
229 return regexes;
230}
231
232
233/**
234 * Free all memory reserved for a set of regexes created by read_from_file.
235 *
236 * @param regexes NULL-terminated array of regexes.
237 */
238void
239GNUNET_REGEX_free_from_file (char **regexes)
240{
241 unsigned int i;
242
243 for (i = 0; regexes[i]; i++)
244 GNUNET_free (regexes[i]);
245 GNUNET_free (regexes);
246}
247
248/* end of regex_test_lib.c */ \ No newline at end of file