Make it easier to try GTK 3.6
[metze/wireshark/wip.git] / conditions.c
1 /* conditions.c
2  * Implementation for condition handler.
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #include "config.h"
26
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include "conditions.h"
31
32 /* container for condition classes */
33 static GHashTable *classes = NULL;
34
35 /* condition data structure declaration */
36 struct condition{
37   char       *class_id;
38   void       *user_data;
39   _cnd_eval   eval_func;
40   _cnd_reset  reset_func;
41 };
42
43 /* structure used to store class functions in GHashTable */
44 typedef struct _cnd_class{
45   _cnd_constr constr_func;
46   _cnd_destr  destr_func;
47   _cnd_eval   eval_func;
48   _cnd_reset  reset_func;
49 } _cnd_class;
50
51 /* helper function prototypes */
52 static void _cnd_init(void);
53 static void _cnd_find_hash_key_for_class_id(gpointer, gpointer, gpointer);
54
55 condition *cnd_new(const char *class_id, ...) {
56   va_list     ap;
57   condition  *cnd     = NULL;
58   condition  *cnd_ref = NULL;
59   _cnd_class *cls     = NULL;
60   char       *id      = NULL;
61
62   /* check if hash table is already initialized */
63   _cnd_init();
64
65   /* get class structure for this id */
66   if ((cls = (_cnd_class *)g_hash_table_lookup(classes, class_id)) == NULL) {
67     g_warning("cnd_new: Couldn't find class ID \"%s\"", class_id);
68     return NULL;
69   }
70
71   /* initialize the basic structure */
72   if ((cnd_ref = (condition *)g_malloc(sizeof(condition))) == NULL)
73     return NULL;
74   cnd_ref->user_data  = NULL;
75   cnd_ref->eval_func  = cls->eval_func;
76   cnd_ref->reset_func = cls->reset_func;
77
78   cnd_ref->class_id = g_strdup(class_id);
79
80   /* perform class specific initialization */
81   va_start(ap, class_id);
82   cnd = (cls->constr_func)(cnd_ref, ap);
83   va_end(ap);
84
85   /* check for successful construction */
86   if (cnd == NULL) {
87     g_free(cnd_ref);
88     g_free(id);
89   }
90   return cnd;
91 } /* END cnd_new() */
92
93 void cnd_delete(condition *cnd) {
94   _cnd_class *cls = NULL;
95   const char* class_id;
96   /* check for valid pointer */
97   if (cnd == NULL)
98     return;
99
100   class_id = cnd->class_id;
101   /* check if hash table is already initialized */
102   _cnd_init();
103   /* get the condition class */
104   cls = (_cnd_class *)g_hash_table_lookup(classes, class_id);
105   /* call class specific destructor */
106   if (cls != NULL)
107     (cls->destr_func)(cnd);
108   /* free memory */
109   g_free(cnd->class_id);
110   /* free basic structure */
111   g_free(cnd);
112 } /* END cnd_delete() */
113
114 gboolean cnd_eval(condition *cnd, ...) {
115   va_list ap;
116   gboolean ret_val = FALSE;
117   /* validate cnd */
118   if (cnd == NULL)
119     return FALSE;
120   /* call specific handler */
121   va_start(ap, cnd);
122   ret_val = (cnd->eval_func)(cnd, ap);
123   va_end(ap);
124   return ret_val;
125 } /*  END cnd_eval() */
126
127 void cnd_reset(condition *cnd) {
128   if (cnd != NULL)
129     (cnd->reset_func)(cnd);
130 } /* END cnd_reset() */
131
132 void* cnd_get_user_data(condition *cnd) {
133   return cnd->user_data;
134 } /* END cnd_get_user_data() */
135
136 void cnd_set_user_data(condition *cnd, void *user_data) {
137   cnd->user_data = user_data;
138 } /* END cnd_set_user_data() */
139
140 gboolean cnd_register_class(const char *class_id,
141                             _cnd_constr constr_func,
142                             _cnd_destr  destr_func,
143                             _cnd_eval   eval_func,
144                             _cnd_reset  reset_func) {
145   char *key = NULL;
146   _cnd_class *cls = NULL;
147   /* check for valid parameters */
148   if ((constr_func == NULL) || (destr_func == NULL) ||
149       (eval_func == NULL) || (reset_func == NULL) || (class_id == NULL))
150     return FALSE;
151   /* check if hash table is already initialized */
152   _cnd_init();
153   /* check for unique class id */
154   if (g_hash_table_lookup(classes, class_id) != NULL) {
155     g_warning("cnd_register_class: Duplicate class ID \"%s\"", class_id);
156     return FALSE;
157   }
158   /* GHashTable keys need to be persistent for the lifetime of the hash
159      table. Allocate memory and copy the class id which we use as key. */
160   key = g_strdup(class_id);
161   /* initialize class structure */
162   if ((cls = (_cnd_class*)g_malloc(sizeof(_cnd_class))) == NULL) {
163     g_free(key);
164     return FALSE;
165   }
166   cls->constr_func = constr_func;
167   cls->destr_func  = destr_func;
168   cls->eval_func   = eval_func;
169   cls->reset_func  = reset_func;
170   /* insert new class */
171   g_hash_table_insert(classes, key, cls);
172   return TRUE;
173 } /* END cnd_register_class() */
174
175 static char *pkey = NULL;
176 void cnd_unregister_class(const char* class_id) {
177   const char *key = (const char*)class_id;
178   _cnd_class *cls = NULL;
179   /* check if hash table is already initialized */
180   _cnd_init();
181   /* find the key for this class id and store it in 'pkey' */
182   g_hash_table_foreach(classes,
183                        _cnd_find_hash_key_for_class_id,
184                        (gpointer)key);
185   /* find the class structure for this class id */
186   cls = (_cnd_class*)g_hash_table_lookup(classes, class_id);
187   /* remove constructor from hash table */
188   g_hash_table_remove(classes, class_id);
189   /* free the key */
190   g_free(pkey);
191   pkey = NULL;
192   /* free the value */
193   g_free(cls);
194 } /* END cnd_unregister_class() */
195
196 /*
197  * Initialize hash table.
198  */
199 static void _cnd_init(void) {
200   if (classes != NULL)
201     return;
202   /* create hash table, we use strings as keys */
203   classes = g_hash_table_new(g_str_hash, g_str_equal);
204 } /* END _cnd_init() */
205
206 /*
207  * Callback for function 'g_hash_table_foreach()'.
208  * We don't keep references to hash table keys. Keys have memory allocated
209  * which must be freed when they are not used anymore. This function finds
210  * the reference to a key corresponding to a particular class id. The reference
211  * to the key is stored in a global variable.
212  */
213 void _cnd_find_hash_key_for_class_id(gpointer key,
214                                      gpointer value _U_,
215                                      gpointer user_data) {
216   char *class_id  = (char *)user_data;
217   char *key_value = (char *)key;
218   if (strcmp(class_id, key_value) == 0)
219     pkey = key_value;
220 } /* END _cnd_find_hash_key_for_class_id() */
221
222 /*
223  * Editor modelines
224  *
225  * Local Variables:
226  * c-basic-offset: 2
227  * tab-width: 8
228  * indent-tabs-mode: nil
229  * End:
230  *
231  * ex: set shiftwidth=2 tabstop=8 expandtab:
232  * :indentSize=2:tabSize=8:noTabs=true:
233  */