The UAT gui starts to work
[obnox/wireshark/wip.git] / epan / uat.c
1 /*
2  *  uat.c
3  *
4  * $Id$
5  *
6  *  User Accessible Tables
7  *  Mantain an array of user accessible data strucures
8  *
9  * (c) 2007, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 2001 Gerald Combs
14  * 
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  * 
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  * 
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <ctype.h>
38 #include <stdarg.h>
39
40 #include <glib.h>
41 #include <epan/emem.h>
42 #include <epan/filesystem.h>
43
44 #include "uat-int.h"
45
46 static GPtrArray* all_uats = NULL;
47
48 void uat_init(void) {
49         all_uats = g_ptr_array_new();
50 }
51
52 uat_t* uat_start(const char* name,
53                                  size_t size,
54                                  char* filename,
55                                  void** data_ptr,
56                                  guint* num_items_ptr,
57                                  uat_copy_cb_t copy_cb,
58                                  uat_update_cb_t update_cb,
59                                  uat_free_cb_t free_cb) {
60         
61         uat_t* uat = g_malloc(sizeof(uat_t));
62
63         if (!all_uats)
64                 all_uats = g_ptr_array_new();
65         
66         g_ptr_array_add(all_uats,uat);
67         
68         g_assert(name && size && filename && data_ptr && num_items_ptr);
69         
70         uat->name = g_strdup(name);
71         uat->record_size = size;
72         uat->filename = g_strdup(filename);
73         uat->user_ptr = data_ptr;
74         uat->nrows_p = num_items_ptr;
75         uat->copy_cb = copy_cb;
76         uat->update_cb = update_cb;
77         uat->free_cb = free_cb;
78         
79         uat->fields = NULL;
80         uat->ncols = 0;
81         uat->user_data = g_array_new(FALSE,FALSE,uat->record_size);
82         uat->finalized = FALSE;
83         uat->rep = NULL;
84         uat->free_rep = NULL;
85         
86         return uat;
87 }
88
89 void uat_add_field(uat_t* uat,
90                                    const char* name,
91                                    uat_text_mode_t mode,
92                                    uat_fld_chk_cb_t chk_cb,
93                                    uat_fld_set_cb_t set_cb,
94                                    uat_fld_tostr_cb_t tostr_cb) {
95         
96         uat_fld_t* f = g_malloc(sizeof(uat_fld_t));
97
98         g_assert( name && set_cb && tostr_cb && (! uat->finalized ) 
99                           && (mode == PT_TXTMOD_STRING || mode == PT_TXTMOD_HEXBYTES) );
100         
101         f->name = g_strdup(name);
102         f->mode = mode;
103         f->chk_cb = chk_cb;
104         f->set_cb = set_cb;
105         f->tostr_cb = tostr_cb;
106
107         f->rep = NULL;
108         f->free_rep = NULL;     
109         f->colnum = uat->ncols;
110         f->next = NULL;
111
112         uat->ncols++;
113         
114         if (uat->fields) {
115                 uat_fld_t* c;
116                 for (c = uat->fields; c->next; c = c->next) ;
117                 c->next = f;
118         } else {
119                 uat->fields = f;        
120         }
121 }
122
123 void uat_finalize(uat_t* uat) {
124         UAT_UPDATE(uat);
125         uat->finalized = TRUE;
126 }
127
128 uat_t* uat_new(const char* uat_name,
129                            size_t size,
130                            char* filename,
131                            void** data_ptr,
132                            guint* numitems_ptr,
133                            uat_copy_cb_t copy_cb,
134                            uat_update_cb_t update_cb,
135                            uat_free_cb_t free_cb,
136                            char** error,
137                            ...) {
138         uat_t* uat = uat_start(uat_name, size, filename, data_ptr, numitems_ptr, copy_cb, update_cb, free_cb);
139         va_list ap;
140         char* name;
141         uat_text_mode_t mode;
142         uat_fld_chk_cb_t chk_cb;
143         uat_fld_set_cb_t set_cb;
144         uat_fld_tostr_cb_t tostr_cb;
145         va_start(ap,error);
146         
147         name = va_arg(ap,char*);
148         
149         do {
150                 mode = va_arg(ap,uat_text_mode_t);
151                 chk_cb = va_arg(ap,uat_fld_chk_cb_t);
152                 set_cb = va_arg(ap,uat_fld_set_cb_t);
153                 tostr_cb = va_arg(ap,uat_fld_tostr_cb_t);
154
155                 uat_add_field(uat, name, mode, chk_cb, set_cb, tostr_cb);
156                 
157                 name = va_arg(ap,char*);
158         } while (name);
159         
160         va_end(ap);
161         
162         uat_finalize(uat);
163         
164         uat_load(uat,error);
165         
166         return uat;
167 }
168
169 void* uat_add_record(uat_t* uat, const void* data) {
170         void* rec;
171         
172         g_assert( uat->finalized );
173         
174         g_array_append_vals (uat->user_data, data, 1);
175         
176         rec = uat->user_data->data + (uat->record_size * (uat->user_data->len-1));
177         
178         if (uat->copy_cb) {
179                 uat->copy_cb(rec, data, uat->record_size);
180         }
181         
182         
183         UAT_UPDATE(uat);
184         
185         return rec;
186 }
187
188 void uat_remove_record_idx(uat_t* uat, guint idx) {
189         
190         g_assert( uat->finalized && idx < uat->user_data->len);
191
192         g_array_remove_index(uat->user_data, idx);
193         
194         UAT_UPDATE(uat);
195
196 }
197
198
199 gchar* uat_get_actual_filename(uat_t* uat, gboolean for_writing) {
200         gchar* pers_fname =  get_persconffile_path(uat->filename,for_writing);
201         
202         if (! file_exists(pers_fname)) {
203                 gchar* data_fname = get_datafile_path(uat->filename);
204                 
205                 if (file_exists(data_fname)) {
206                         return data_fname;
207                 }
208         }
209         
210         return pers_fname;
211 }
212
213 static void putfld(FILE* fp, void* rec, uat_fld_t* f) {
214         guint fld_len;
215         char* fld_ptr;
216         
217         f->tostr_cb(rec,&fld_ptr,&fld_len);
218         
219         switch(f->mode){
220                 case  PT_TXTMOD_STRING: {
221                         guint i;
222                         
223                         putc('"',fp);
224                         
225                         for(i=0;i<fld_len;i++) {
226                                 char c = fld_ptr[i];
227                                 
228                                 if (c == '"') {
229                                         fputs("\134\042",fp);
230                                 } else if (isprint(c)) {
231                                         putc(c,fp);
232                                 } else {
233                                         fprintf(fp,"\\x%.2x",c);
234                                 }
235                         }
236                         
237                         putc('"',fp);
238                         return;
239                 }
240                 case PT_TXTMOD_HEXBYTES: {
241                         guint i;
242                         
243                         for(i=0;i<fld_len;i++) {
244                                 fprintf(fp,"%.2x",fld_ptr[i]);
245                         }
246                         
247                         return;
248                 }
249                 default:
250                         g_assert_not_reached();
251         }
252 }
253
254 gboolean uat_save(uat_t* uat, char** error) {
255         guint i;
256         gchar* fname = uat_get_actual_filename(uat,TRUE);
257         FILE* fp = fopen(fname,"w");
258         
259
260         if (!fp) {
261                 *error = ep_strdup_printf("uat_save: error opening '%s': %s",fname,strerror(errno));
262                 return FALSE;
263         }
264
265         *error = NULL;
266
267         for ( i = 0 ; i < uat->user_data->len - 1 ; i++ ) {
268                 void* rec = uat->user_data->data + (uat->record_size * (uat->user_data->len-1));
269                 uat_fld_t* f;
270                 
271                 f = uat->fields;
272                 
273                 putfld(fp, rec, f);
274                         
275                 while (( f = f->next )) {
276                         fputs(",",fp);
277                         putfld(fp, rec, f);                             
278                 }
279
280                 fputs("\n",fp);
281         }
282
283         fclose(fp);
284         
285         return TRUE;
286 }
287
288 void uat_destroy(uat_t* uat) {
289         g_ptr_array_remove(all_uats,uat);
290         
291 }
292
293 void* uat_dup(uat_t* uat, guint* len_p) {
294         guint size = (uat->record_size * uat->user_data->len);
295         *len_p = size;
296         return size ? g_memdup(uat->user_data->data,size) : NULL ;
297 }
298
299 void* uat_se_dup(uat_t* uat, guint* len_p) {
300         guint size = (uat->record_size * uat->user_data->len);
301         *len_p = size;
302         return size ? se_memdup(uat->user_data->data,size) : NULL ;
303 }
304
305 void uat_cleanup(void) {
306
307         while( all_uats->len ) {
308                 uat_destroy((uat_t*)all_uats->pdata);
309         }
310
311         g_ptr_array_free(all_uats,TRUE);
312 }
313