Document the "-o dec" changes.
[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 #include <string.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include "conditions.h"
29
30 /* container for condition classes */
31 static GHashTable* classes = NULL;
32
33 /* condition data structure declaration */
34 struct condition{
35   char* class_id;
36   void* user_data;
37   _cnd_eval eval_func;
38   _cnd_reset reset_func;
39 };
40
41 /* structure used to store class functions in GHashTable */
42 typedef struct _cnd_class{
43   _cnd_constr constr_func;
44   _cnd_destr destr_func;
45   _cnd_eval eval_func;
46   _cnd_reset reset_func;
47 } _cnd_class;
48
49 /* helper function prototypes */
50 static void _cnd_init(void);
51 static void _cnd_find_hash_key_for_class_id(gpointer, gpointer, gpointer);
52
53 condition* cnd_new(const char* class_id, ...){
54   va_list ap;
55   condition *cnd = NULL, *cnd_ref = NULL;
56   _cnd_class *cls = NULL;
57   char* id = NULL;
58   /* check if hash table is already initialized */
59   _cnd_init();
60   /* get class structure for this id */
61   if((cls = (_cnd_class*)g_hash_table_lookup(classes, class_id)) == NULL)
62     return NULL;
63   /* initialize the basic structure */
64   if((cnd_ref = (condition*)g_malloc(sizeof(condition))) == NULL) return NULL;
65   cnd_ref->user_data = NULL;
66   cnd_ref->eval_func = cls->eval_func;
67   cnd_ref->reset_func = cls->reset_func;
68   /* copy the class id */
69   if((id = (char*)g_malloc(strlen(class_id)+1)) == NULL){
70     g_free(cnd_ref);
71     return NULL;
72   }
73   strncpy(id, class_id, strlen(class_id));
74   id[strlen(class_id)] = '\0';
75   cnd_ref->class_id = id;
76   /* perform class specific initialization */
77   va_start(ap, class_id);
78   cnd = (cls->constr_func)(cnd_ref, ap);
79   va_end(ap);
80   /* check for successful construction */
81   if(cnd == NULL){
82     g_free(cnd_ref);
83     g_free(id);
84   }
85   return cnd;
86 } /* END cnd_new() */
87
88 void cnd_delete(condition *cnd){
89   _cnd_class *cls = NULL;
90   const char* class_id;
91   /* check for valid pointer */
92   if(cnd == NULL) return;
93
94   class_id = cnd->class_id;
95   /* check if hash table is already initialized */
96   _cnd_init();
97   /* get the condition class */
98   cls = (_cnd_class*)g_hash_table_lookup(classes, class_id);
99   /* call class specific destructor */
100   if(cls != NULL) (cls->destr_func)(cnd);
101   /* free memory */
102   g_free(cnd->class_id);
103   /* free basic structure */
104   g_free(cnd);
105 } /* END cnd_delete() */
106
107 gboolean cnd_eval(condition *cnd, ...){
108   va_list ap;
109   gboolean ret_val = FALSE;
110   /* validate cnd */
111   if(cnd == NULL) return FALSE;
112   /* call specific handler */
113   va_start(ap, cnd);
114   ret_val = (cnd->eval_func)(cnd, ap);
115   va_end(ap);
116   return ret_val;
117 } /*  END cnd_eval() */
118
119 void cnd_reset(condition *cnd){
120   if(cnd != NULL) (cnd->reset_func)(cnd);
121 } /* END cnd_reset() */
122
123 void* cnd_get_user_data(condition *cnd){
124   return cnd->user_data;
125 } /* END cnd_get_user_data() */
126
127 void cnd_set_user_data(condition *cnd, void* user_data){
128   cnd->user_data = user_data;
129 } /* END cnd_set_user_data() */
130
131 gboolean cnd_register_class(const char* class_id,
132                             _cnd_constr constr_func,
133                             _cnd_destr destr_func,
134                             _cnd_eval eval_func,
135                             _cnd_reset reset_func){
136   char* key = NULL;
137   _cnd_class *cls = NULL;
138   /* check for valid parameters */
139   if((constr_func == NULL) || (destr_func == NULL) ||
140      (eval_func == NULL) || (reset_func == NULL) || (class_id == NULL))
141     return FALSE;
142   /* check if hash table is already initialized */
143   _cnd_init();
144   /* check for unique class id */
145   if((cls = (_cnd_class*)g_hash_table_lookup(classes, class_id)) != NULL)
146     return FALSE;
147   /* GHashTable keys need to be persistent for the lifetime of the hash
148      table. Allocate memory and copy the class id which we use as key. */
149   if((key = (char*)g_malloc(strlen(class_id)+1)) == NULL) return FALSE;
150   strncpy(key, class_id, strlen(class_id));
151   key[strlen(class_id)] = '\0';
152   /* initialize class structure */
153   if((cls = (_cnd_class*)g_malloc(sizeof(_cnd_class))) == NULL){
154     g_free(key);
155     return FALSE;
156   }
157   cls->constr_func = constr_func;
158   cls->destr_func = destr_func;
159   cls->eval_func = eval_func;
160   cls->reset_func = reset_func;
161   /* insert new class */
162   g_hash_table_insert(classes, key, cls);
163   return TRUE;
164 } /* END cnd_register_class() */
165
166 static char* pkey = NULL;
167 void cnd_unregister_class(const char* class_id){
168   const char *key = (const char*)class_id;
169   _cnd_class *cls = NULL;
170   /* check if hash table is already initialized */
171   _cnd_init();
172   /* find the key for this class id and store it in 'pkey' */
173   g_hash_table_foreach(classes,
174                        _cnd_find_hash_key_for_class_id,
175                        (gpointer)key);
176   /* find the class structure for this class id */
177   cls = (_cnd_class*)g_hash_table_lookup(classes, class_id);
178   /* remove constructor from hash table */
179   g_hash_table_remove(classes, class_id);
180   /* free the key */
181   g_free(pkey);
182   pkey = NULL;
183   /* free the value */
184   g_free(cls);
185 } /* END cnd_unregister_class() */
186
187 /*
188  * Initialize hash table.
189  */
190 static void _cnd_init(void){
191   if(classes != NULL) return;
192   /* create hash table, we use strings as keys */
193   classes = g_hash_table_new(g_str_hash, g_str_equal);
194 } /* END _cnd_init() */
195
196 /*
197  * Callback for function 'g_hash_table_foreach()'.
198  * We don't keep references to hash table keys. Keys have memory allocated
199  * which must be freed when they are not used anymore. This function finds
200  * the reference to a key corresponding to a particular class id. The reference
201  * to the key is stored in a global variable.
202  */
203 void _cnd_find_hash_key_for_class_id(gpointer key,
204                                      gpointer value _U_,
205                                      gpointer user_data){
206   char* class_id = (char*)user_data;
207   char* key_value = (char*)key;
208   if(strcmp(class_id, key_value) == 0) pkey = key;
209 } /* END _cnd_find_hash_key_for_class_id() */