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