From Harald Welte:
[obnox/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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include "conditions.h"
33
34 /* container for condition classes */
35 static GHashTable* classes = NULL;
36
37 /* condition data structure declaration */
38 struct condition{
39   char* class_id;
40   void* user_data;
41   _cnd_eval eval_func;
42   _cnd_reset reset_func;
43 };
44
45 /* structure used to store class functions in GHashTable */
46 typedef struct _cnd_class{
47   _cnd_constr constr_func;
48   _cnd_destr destr_func;
49   _cnd_eval eval_func;
50   _cnd_reset reset_func;
51 } _cnd_class;
52
53 /* helper function prototypes */
54 static void _cnd_init(void);
55 static void _cnd_find_hash_key_for_class_id(gpointer, gpointer, gpointer);
56
57 condition* cnd_new(const char* class_id, ...){
58   va_list ap;
59   condition *cnd = NULL, *cnd_ref = NULL;
60   _cnd_class *cls = NULL;
61   char* id = NULL;
62
63   /* check if hash table is already initialized */
64   _cnd_init();
65
66   /* get class structure for this id */
67   if((cls = (_cnd_class*)g_hash_table_lookup(classes, class_id)) == NULL) {
68     g_warning("cnd_new: Couldn't find class ID \"%s\"", class_id);
69     return NULL;
70   }
71
72   /* initialize the basic structure */
73   if((cnd_ref = (condition*)g_malloc(sizeof(condition))) == NULL) 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) return;
98
99   class_id = cnd->class_id;
100   /* check if hash table is already initialized */
101   _cnd_init();
102   /* get the condition class */
103   cls = (_cnd_class*)g_hash_table_lookup(classes, class_id);
104   /* call class specific destructor */
105   if(cls != NULL) (cls->destr_func)(cnd);
106   /* free memory */
107   g_free(cnd->class_id);
108   /* free basic structure */
109   g_free(cnd);
110 } /* END cnd_delete() */
111
112 gboolean cnd_eval(condition *cnd, ...){
113   va_list ap;
114   gboolean ret_val = FALSE;
115   /* validate cnd */
116   if(cnd == NULL) return FALSE;
117   /* call specific handler */
118   va_start(ap, cnd);
119   ret_val = (cnd->eval_func)(cnd, ap);
120   va_end(ap);
121   return ret_val;
122 } /*  END cnd_eval() */
123
124 void cnd_reset(condition *cnd){
125   if(cnd != NULL) (cnd->reset_func)(cnd);
126 } /* END cnd_reset() */
127
128 void* cnd_get_user_data(condition *cnd){
129   return cnd->user_data;
130 } /* END cnd_get_user_data() */
131
132 void cnd_set_user_data(condition *cnd, void* user_data){
133   cnd->user_data = user_data;
134 } /* END cnd_set_user_data() */
135
136 gboolean cnd_register_class(const char* class_id,
137                             _cnd_constr constr_func,
138                             _cnd_destr destr_func,
139                             _cnd_eval eval_func,
140                             _cnd_reset reset_func){
141   char* key = NULL;
142   _cnd_class *cls = NULL;
143   /* check for valid parameters */
144   if((constr_func == NULL) || (destr_func == NULL) ||
145      (eval_func == NULL) || (reset_func == NULL) || (class_id == NULL))
146     return FALSE;
147   /* check if hash table is already initialized */
148   _cnd_init();
149   /* check for unique class id */
150   if(g_hash_table_lookup(classes, class_id) != NULL) {
151     g_warning("cnd_register_class: Duplicate class ID \"%s\"", class_id);
152     return FALSE;
153   }
154   /* GHashTable keys need to be persistent for the lifetime of the hash
155      table. Allocate memory and copy the class id which we use as key. */
156   key = g_strdup(class_id);
157   /* initialize class structure */
158   if((cls = (_cnd_class*)g_malloc(sizeof(_cnd_class))) == NULL){
159     g_free(key);
160     return FALSE;
161   }
162   cls->constr_func = constr_func;
163   cls->destr_func = destr_func;
164   cls->eval_func = eval_func;
165   cls->reset_func = reset_func;
166   /* insert new class */
167   g_hash_table_insert(classes, key, cls);
168   return TRUE;
169 } /* END cnd_register_class() */
170
171 static char* pkey = NULL;
172 void cnd_unregister_class(const char* class_id){
173   const char *key = (const char*)class_id;
174   _cnd_class *cls = NULL;
175   /* check if hash table is already initialized */
176   _cnd_init();
177   /* find the key for this class id and store it in 'pkey' */
178   g_hash_table_foreach(classes,
179                        _cnd_find_hash_key_for_class_id,
180                        (gpointer)key);
181   /* find the class structure for this class id */
182   cls = (_cnd_class*)g_hash_table_lookup(classes, class_id);
183   /* remove constructor from hash table */
184   g_hash_table_remove(classes, class_id);
185   /* free the key */
186   g_free(pkey);
187   pkey = NULL;
188   /* free the value */
189   g_free(cls);
190 } /* END cnd_unregister_class() */
191
192 /*
193  * Initialize hash table.
194  */
195 static void _cnd_init(void){
196   if(classes != NULL) return;
197   /* create hash table, we use strings as keys */
198   classes = g_hash_table_new(g_str_hash, g_str_equal);
199 } /* END _cnd_init() */
200
201 /*
202  * Callback for function 'g_hash_table_foreach()'.
203  * We don't keep references to hash table keys. Keys have memory allocated
204  * which must be freed when they are not used anymore. This function finds
205  * the reference to a key corresponding to a particular class id. The reference
206  * to the key is stored in a global variable.
207  */
208 void _cnd_find_hash_key_for_class_id(gpointer key,
209                                      gpointer value _U_,
210                                      gpointer user_data){
211   char* class_id = (char*)user_data;
212   char* key_value = (char*)key;
213   if(strcmp(class_id, key_value) == 0) pkey = key_value;
214 } /* END _cnd_find_hash_key_for_class_id() */
215
216 /*
217  * Editor modelines
218  *
219  * Local Variables:
220  * c-basic-offset: 2
221  * tab-width: 8
222  * indent-tabs-mode: nil
223  * End:
224  *
225  * ex: set shiftwidth=2 tabstop=8 expandtab:
226  * :indentSize=2:tabSize=8:noTabs=true:
227  */