4abdeca986dde39a1916cd252036d4b415096572
[metze/wireshark/wip.git] / epan / ftypes / ftype-string.c
1 /*
2  * $Id: ftype-string.c,v 1.15 2003/11/25 13:20:36 sahlberg Exp $
3  *
4  * Ethereal - Network traffic analyzer
5  * By Gerald Combs <gerald@ethereal.com>
6  * Copyright 2001 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <ftypes-int.h>
28 #include <string.h>
29
30 static void
31 string_fvalue_new(fvalue_t *fv)
32 {
33         fv->value.string = NULL;
34 }
35
36 static void
37 string_fvalue_free(fvalue_t *fv)
38 {
39         if (fv->value.string) {
40                 g_free(fv->value.string);
41         }
42 }
43
44 static void
45 string_fvalue_set(fvalue_t *fv, gpointer value, gboolean already_copied)
46 {
47         g_assert(value != NULL);
48
49         /* Free up the old value, if we have one */
50         string_fvalue_free(fv);
51
52         if (already_copied) {
53                 fv->value.string = value;
54         }
55         else {
56                 fv->value.string = g_strdup(value);
57         }
58 }
59
60 static int
61 string_repr_len(fvalue_t *fv, ftrepr_t rtype)
62 {
63         gchar *p, c;
64         int repr_len;
65
66         switch (rtype) {
67                 case FTREPR_DISPLAY:
68                         return strlen(fv->value.string);
69                 case FTREPR_DFILTER:
70                         repr_len = 0;
71                         for (p = fv->value.string; (c = *p) != '\0'; p++) {
72                                 if (c == '\\' || c == '"') {
73                                         /* Backslashes and double-quotes
74                                            must be escaped. */
75                                         repr_len++;
76                                 }
77                                 repr_len++;
78                         }
79                         return repr_len + 2;    /* string plus leading and trailing quotes */
80         }
81         g_assert_not_reached();
82         return -1;
83 }
84
85 static void
86 string_to_repr(fvalue_t *fv, ftrepr_t rtype, char *buf)
87 {
88         gchar *p, c;
89         char *bufp;
90
91         if (rtype == FTREPR_DFILTER) {
92                 bufp = buf;
93                 *bufp++ = '"';
94                 for (p = fv->value.string; (c = *p) != '\0'; p++) {
95                         if (c == '\\' || c == '"') {
96                                 /* Backslashes and double-quotes
97                                    must be escaped. */
98                                 *bufp++ = '\\';
99                         }
100                         *bufp++ = c;
101                 }
102                 *bufp++ = '"';
103                 *bufp = '\0';
104         }
105         else {
106                 strcpy(buf, fv->value.string);
107         }
108 }
109
110
111 static gpointer
112 value_get(fvalue_t *fv)
113 {
114         return fv->value.string;
115 }
116
117 static gboolean
118 val_from_string(fvalue_t *fv, char *s, LogFunc logfunc _U_)
119 {
120         /* Free up the old value, if we have one */
121         string_fvalue_free(fv);
122
123         fv->value.string = g_strdup(s);
124         return TRUE;
125 }
126
127 static gboolean
128 val_from_unparsed(fvalue_t *fv, char *s, gboolean allow_partial_value _U_, LogFunc logfunc)
129 {
130         fvalue_t *fv_bytes;
131
132         /* Free up the old value, if we have one */
133         string_fvalue_free(fv);
134
135         /* Does this look like a byte-string? */
136         fv_bytes = fvalue_from_unparsed(FT_BYTES, s, TRUE, NULL);
137         if (fv_bytes) {
138                 /* Copy the bytes over to a string and terminate it
139                  * with a NUL. XXX - what if the user embeds a NUL
140                  * in the middle of the byte string? */
141                 int num_bytes = fv_bytes->value.bytes->len;
142
143                 fv->value.string = g_malloc(num_bytes + 1);
144                 memcpy(fv->value.string, fv->value.bytes->data, num_bytes);
145                 fv->value.string[num_bytes] = '\0';
146
147                 FVALUE_FREE(fv_bytes);
148                 return TRUE;
149         }
150         else {
151                 /* Just turn it into a string */
152                 return val_from_string(fv, s, logfunc);
153         }
154         g_assert_not_reached();
155 }
156
157 static guint
158 len(fvalue_t *fv)
159 {
160         return strlen(fv->value.string);
161 }
162
163 static void
164 slice(fvalue_t *fv, GByteArray *bytes, guint offset, guint length)
165 {
166         guint8* data;
167
168         data = fv->value.string + offset;
169
170         g_byte_array_append(bytes, data, length);
171 }
172
173
174 static gboolean
175 cmp_eq(fvalue_t *a, fvalue_t *b)
176 {
177         return (strcmp(a->value.string, b->value.string) == 0);
178 }
179
180 static gboolean
181 cmp_ne(fvalue_t *a, fvalue_t *b)
182 {
183         return (strcmp(a->value.string, b->value.string) != 0);
184 }
185
186 static gboolean
187 cmp_gt(fvalue_t *a, fvalue_t *b)
188 {
189         return (strcmp(a->value.string, b->value.string) > 0);
190 }
191
192 static gboolean
193 cmp_ge(fvalue_t *a, fvalue_t *b)
194 {
195         return (strcmp(a->value.string, b->value.string) >= 0);
196 }
197
198 static gboolean
199 cmp_lt(fvalue_t *a, fvalue_t *b)
200 {
201         return (strcmp(a->value.string, b->value.string) < 0);
202 }
203
204 static gboolean
205 cmp_le(fvalue_t *a, fvalue_t *b)
206 {
207         return (strcmp(a->value.string, b->value.string) <= 0);
208 }
209
210 static gboolean
211 cmp_contains(fvalue_t *fv_a, fvalue_t *fv_b)
212 {
213         /* According to
214         * http://www.introl.com/introl-demo/Libraries/C/ANSI_C/string/strstr.html
215         * strstr() returns a non-NULL value if needle is an empty
216         * string. We don't that behavior for cmp_contains. */
217         if (strlen(fv_b->value.string) == 0) {
218                 return FALSE;
219         }
220
221         if (strstr(fv_a->value.string, fv_b->value.string)) {
222                 return TRUE;
223         }
224         else {
225                 return FALSE;
226         }
227 }
228
229 void
230 ftype_register_string(void)
231 {
232
233         static ftype_t string_type = {
234                 "FT_STRING",                    /* name */
235                 "character string",             /* pretty_name */
236                 0,                              /* wire_size */
237                 string_fvalue_new,              /* new_value */
238                 string_fvalue_free,             /* free_value */
239                 val_from_unparsed,              /* val_from_unparsed */
240                 val_from_string,                /* val_from_string */
241                 string_to_repr,                 /* val_to_string_repr */
242                 string_repr_len,                /* len_string_repr */
243
244                 string_fvalue_set,              /* set_value */
245                 NULL,                           /* set_value_integer */
246                 NULL,                           /* set_value_floating */
247
248                 value_get,                      /* get_value */
249                 NULL,                           /* get_value_integer */
250                 NULL,                           /* get_value_floating */
251
252                 cmp_eq,
253                 cmp_ne,
254                 cmp_gt,
255                 cmp_ge,
256                 cmp_lt,
257                 cmp_le,
258                 cmp_contains,                   /* cmp_contains */
259
260                 len,
261                 slice,
262         };
263         static ftype_t stringz_type = {
264                 "FT_STRINGZ",
265                 "character string",
266                 0,
267                 string_fvalue_new,
268                 string_fvalue_free,
269                 val_from_unparsed,              /* val_from_unparsed */
270                 val_from_string,                /* val_from_string */
271                 NULL,                           /* val_to_string_repr */
272                 NULL,                           /* len_string_repr */
273
274                 string_fvalue_set,
275                 NULL,
276                 NULL,
277
278                 value_get,
279                 NULL,
280                 NULL,
281
282                 cmp_eq,
283                 cmp_ne,
284                 cmp_gt,
285                 cmp_ge,
286                 cmp_lt,
287                 cmp_le,
288                 cmp_contains,                   /* cmp_contains */
289
290                 len,
291                 slice,
292         };
293         static ftype_t uint_string_type = {
294                 "FT_UINT_STRING",
295                 "character string",
296                 0,
297                 string_fvalue_new,
298                 string_fvalue_free,
299                 val_from_unparsed,              /* val_from_unparsed */
300                 val_from_string,                /* val_from_string */
301                 NULL,                           /* val_to_string_repr */
302                 NULL,                           /* len_string_repr */
303
304                 string_fvalue_set,
305                 NULL,
306                 NULL,
307
308                 value_get,
309                 NULL,
310                 NULL,
311
312                 cmp_eq,
313                 cmp_ne,
314                 cmp_gt,
315                 cmp_ge,
316                 cmp_lt,
317                 cmp_le,
318                 cmp_contains,                   /* cmp_contains */
319
320                 len,
321                 slice,
322         };
323
324         ftype_register(FT_STRING, &string_type);
325         ftype_register(FT_STRINGZ, &stringz_type);
326         ftype_register(FT_UINT_STRING, &uint_string_type);
327 }