Don't cast away constness.
[metze/wireshark/wip.git] / epan / uat.h
1 /*
2  *  uat.h
3  *
4  *  User Accessible Tables
5  *  Maintain an array of user accessible data strucures
6  *
7  * (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 2001 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
27
28 #ifndef __UAT_H__
29 #define __UAT_H__
30
31 #include <stdlib.h>
32
33 #include "ws_symbol_export.h"
34
35 #ifdef __cplusplus
36 extern "C" {
37 #endif /* __cplusplus */
38
39 /*
40  * uat mantains a dynamically allocated table accessible to the user
41  * via a file and/or gui tables.
42  *
43  * the file is located either in userdir(when first read or when writen) or
44  * in datadir for defaults (read only , it will be always written to userdir).
45  *
46  * the behaviour of the table is controlled by a series of callbacks
47  * the caller must provide.
48  *
49  * BEWARE that the user can change an uat at (almost) any time,
50  * That is pointers to records in an uat are valid only during the call
51  * to the function that obtains them (do not store them).
52  *
53  * UATs are meant for short tables of user data (passwords and such) there's
54  * no quick access, you must iterate through them each time to fetch the record
55  * you are looking for.
56  *
57  * Only users via gui or editing the file can add/remove records your code cannot.
58  */
59
60 /* obscure data type to handle an uat */
61 typedef struct epan_uat uat_t;
62 /********************************************
63  * Callbacks:
64  * these instruct uat on how to deal with user info and data in records
65  ********************************************/
66
67 /********
68  * Callbacks dealing with the entire table
69  ********/
70
71 /*
72  * Post-Update CB
73  *
74  * to be called after to the table has being edited
75  * Will be called once the user clicks the Apply or OK button
76  * optional
77  */
78 typedef void (*uat_post_update_cb_t)(void);
79
80
81 /********
82  * Callbacks dealing with records (these deal with entire records)
83  ********/
84
85 /*
86  * Copy CB
87  * copy(dest,orig,len)
88  *
89  * used to copy a record
90  * optional, memcpy will be used if not given
91  */
92 typedef void* (*uat_copy_cb_t)(void*, const void*, size_t);
93
94 /*
95  * Free CB
96  * free(record)
97  *
98  * destroy a record's child data
99  * (do not free the container, it will be handled by uat)
100  * it is optional, no child data will be freed if no present
101  */
102 typedef void (*uat_free_cb_t)(void*);
103
104 /*
105  * Update CB
106  * update(record,&error)
107  *
108  * to be called after any record fields had been updated
109  * optional, record will be updated always if not given
110  * it will return TRUE if OK or else
111  * it will return FALSE and set *error to inform the user on what's
112  * wrong with the given input
113  * The error string must be allocated with g_malloc() or
114  * a routine that calls it.
115  */
116 typedef gboolean (*uat_update_cb_t)(void *, char**);
117
118
119 /*******
120  * Callbacks for single fields (these deal with single values)
121  * the caller should provide one of these for every field!
122  ********/
123
124 /*
125  * Check CB
126  * chk(record, ptr, len, chk_data, fld_data, &error)
127  *
128  * given an input string (ptr, len) checks if the value is OK for a field in the record.
129  * it will return TRUE if OK or else
130  * it will return FALSE and set *error to inform the user on what's
131  * wrong with the given input
132  * The error string must be allocated with g_malloc() or
133  * a routine that calls it.
134  * optional, if not given any input is considered OK and the set cb will be called
135  */
136 typedef gboolean (*uat_fld_chk_cb_t)(void*, const char*, unsigned, const void*, const void*, char**);
137
138 /*
139  * Set Field CB
140  * set(record, ptr, len, set_data, fld_data)
141  *
142  * given an input string (ptr, len) sets the value of a field in the record,
143  * it is mandatory
144  */
145 typedef void (*uat_fld_set_cb_t)(void*, const char*, unsigned, const void*, const void*);
146
147 /*
148  * Convert-to-string CB
149  * tostr(record, &out_ptr, &out_len, tostr_data, fld_data)
150  *
151  * given a record returns a string representation of the field
152  * mandatory
153  */
154 typedef void (*uat_fld_tostr_cb_t)(void*, const char**, unsigned*, const void*, const void*);
155
156 /***********
157  * Text Mode
158  *
159  * used for file and dialog representation of fields in columns,
160  * when the file is read it modifies the way the value is passed back to the fld_set_cb
161  * (see definition bellow for description)
162  ***********/
163
164 typedef enum _uat_text_mode_t {
165         PT_TXTMOD_NONE,
166         /* not used */
167
168         PT_TXTMOD_STRING,
169         /*
170          file:
171                  reads:
172                          ,"\x20\x00\x30", as " \00",3
173                          ,"", as "",0
174                          ,, as NULL,0
175                  writes:
176                          ,"\x20\x30\x00\x20", for " 0\0 ",4
177                          ,"", for *, 0
178                          ,, for NULL, *
179          dialog:
180                  accepts \x?? and other escapes
181                  gets "",0 on empty string
182          */
183         PT_TXTMOD_HEXBYTES,
184         /*
185          file:
186                  reads:
187                          ,A1b2C3d4, as "\001\002\003\004",4
188                          ,, as NULL,0
189                  writes:
190                          ,, on NULL, *
191                          ,a1b2c3d4, on "\001\002\003\004",4
192          dialog:
193                  "a1b2c3d4" as "\001\002\003\004",4
194                  "a1 b2:c3d4" as "\001\002\003\004",4
195                  "" as NULL,0
196                  "invalid" as NULL,3
197                  "a1b" as NULL, 1
198          */
199         PT_TXTMOD_ENUM,
200
201         PT_TXTMOD_FILENAME,
202         /* processed like a PT_TXTMOD_STRING, but shows a filename dialog */
203         PT_TXTMOD_DIRECTORYNAME
204         /* processed like a PT_TXTMOD_STRING, but shows a directory dialog */
205 } uat_text_mode_t;
206
207 /*
208  * Fields
209  *
210  *
211  */
212 typedef struct _uat_field_t {
213         const char* name;
214         const char* title;
215         uat_text_mode_t mode;
216
217         struct {
218                 uat_fld_chk_cb_t chk;
219                 uat_fld_set_cb_t set;
220                 uat_fld_tostr_cb_t tostr;
221         } cb;
222
223         struct {
224                 const void* chk;
225                 const void* set;
226                 const void* tostr;
227         } cbdata;
228
229         const void* fld_data;
230
231         const char* desc;
232         struct _fld_data_t* priv;
233 } uat_field_t;
234
235 #define FLDFILL NULL
236 #define UAT_END_FIELDS {NULL,NULL,PT_TXTMOD_NONE,{0,0,0},{0,0,0},0,0,FLDFILL}
237
238 /*
239  * Flags to indicate what the settings in this UAT affect.
240  * This is used when UATs are changed interactively, to indicate what needs
241  * to be redone when the UAT is changed.
242  */
243 #define UAT_AFFECTS_DISSECTION  0x00000001      /* affects packet dissection */
244 #define UAT_AFFECTS_FIELDS      0x00000002      /* affects what named fields exist */
245
246 /** Create a new uat
247  *
248  * @param name The name of the table
249  * @param size The size of the structure
250  * @param filename The filename to be used (either in userdir or datadir)
251  * @param from_profile TRUE if profile directory to be used
252  * @param data_ptr Although a void*, this is really a pointer to a null terminated array of pointers to the data
253  * @param num_items_ptr A pointer with number of items
254  * @param flags flags indicating what this UAT affects
255  * @param help A pointer to help text
256  * @param copy_cb A function that copies the data in the struct
257  * @param update_cb Will be called when a record is updated
258  * @param free_cb Will be called to destroy a struct in the dataset
259  * @param post_update_cb Will be called once the user clicks the Apply or OK button
260  * @param flds_array A pointer to an array of uat_field_t structs
261  *
262  * @return A freshly-allocated and populated uat_t struct.
263  */
264 WS_DLL_PUBLIC
265 uat_t* uat_new(const char* name,
266                            size_t size,
267                            const char* filename,
268                            gboolean from_profile,
269                            void* data_ptr,
270                            guint* num_items_ptr,
271                            guint flags,
272                            const char* help,
273                            uat_copy_cb_t copy_cb,
274                            uat_update_cb_t update_cb,
275                            uat_free_cb_t free_cb,
276                            uat_post_update_cb_t post_update_cb,
277                            uat_field_t* flds_array);
278
279 /** Populate a uat using its file.
280  *
281  * @param uat_in Pointer to a uat. Must not be NULL.
282  * @param err Upon failure, points to an error string.
283  *
284  * @return TRUE on success, FALSE on failure.
285  */
286 WS_DLL_PUBLIC
287 gboolean uat_load(uat_t* uat_in, char** err);
288
289 /** Create or update a single uat entry using a string.
290  *
291  * @param uat_in Pointer to a uat. Must not be NULL.
292  * @param entry The string representation of the entry. Format must match
293  * what's written to the uat's output file.
294  * @param err Upon failure, points to an error string.
295  *
296  * @return TRUE on success, FALSE on failure.
297  */
298 gboolean uat_load_str(uat_t* uat_in, char* entry, char** err);
299
300 /** Given a uat name or filename, find its pointer.
301  *
302  * @param name The name or filename of the uat
303  *
304  * @return A pointer to the uat on success, NULL on failure.
305  */
306 uat_t *uat_find(gchar *name);
307
308 WS_DLL_PUBLIC
309 uat_t* uat_get_table_by_name(const char* name);
310
311 /*
312  * Some common uat_fld_chk_cbs
313  */
314 WS_DLL_PUBLIC
315 gboolean uat_fld_chk_str(void*, const char*, unsigned, const void*, const void*, char** err);
316 gboolean uat_fld_chk_oid(void*, const char*, unsigned, const void*, const void*, char** err);
317 WS_DLL_PUBLIC
318 gboolean uat_fld_chk_proto(void*, const char*, unsigned, const void*, const void*, char** err);
319 WS_DLL_PUBLIC
320 gboolean uat_fld_chk_num_dec(void*, const char*, unsigned, const void*, const void*, char** err);
321 WS_DLL_PUBLIC
322 gboolean uat_fld_chk_num_hex(void*, const char*, unsigned, const void*, const void*, char** err);
323 WS_DLL_PUBLIC
324 gboolean uat_fld_chk_enum(void*, const char*, unsigned, const void*, const void*, char**);
325 WS_DLL_PUBLIC
326 gboolean uat_fld_chk_range(void*, const char*, unsigned, const void*, const void*, char**);
327
328 typedef void (*uat_cb_t)(void* uat,void* user_data);
329 WS_DLL_PUBLIC
330 void uat_foreach_table(uat_cb_t cb,void* user_data);
331 void uat_unload_all(void);
332
333 char* uat_undquote(const char* si, guint in_len, guint* len_p);
334 char* uat_unbinstring(const char* si, guint in_len, guint* len_p);
335 char* uat_unesc(const char* si, guint in_len, guint* len_p);
336 char* uat_esc(const char* buf, guint len);
337
338 /* Some strings entirely made of ... already declared */
339
340 WS_DLL_PUBLIC
341 gboolean uat_fld_chk_str_isprint(void*, const char*, unsigned, const void*, const void*, char**);
342
343 WS_DLL_PUBLIC
344 gboolean uat_fld_chk_str_isalpha(void*, const char*, unsigned, const void*, const void*, char**);
345
346 WS_DLL_PUBLIC
347 gboolean uat_fld_chk_str_isalnum(void*, const char*, unsigned, const void*, const void*, char**);
348
349 WS_DLL_PUBLIC
350 gboolean uat_fld_chk_str_isdigit(void*, const char*, unsigned, const void*, const void*, char**);
351
352 WS_DLL_PUBLIC
353 gboolean uat_fld_chk_str_isxdigit(void*, const char*, unsigned, const void*, const void*, char**);
354
355
356 /*
357  * Macros
358  *   to define basic uat_fld_set_cbs, uat_fld_tostr_cbs
359  *   for those elements in uat_field_t array
360  */
361
362 #ifdef __cplusplus
363 #define UNUSED_PARAMETER(n)
364 #else
365 #define UNUSED_PARAMETER(n) n _U_
366 #endif
367
368 /*
369  * CSTRING macros,
370  *    a simple c-string contained in (((rec_t*)rec)->(field_name))
371  */
372 #define UAT_CSTRING_CB_DEF(basename,field_name,rec_t) \
373 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
374     char* new_buf = g_strndup(buf,len); \
375         g_free((((rec_t*)rec)->field_name)); \
376         (((rec_t*)rec)->field_name) = new_buf; } \
377 static void basename ## _ ## field_name ## _tostr_cb(void* rec, const char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
378                 if (((rec_t*)rec)->field_name ) { \
379                         *out_ptr = g_strdup((((rec_t*)rec)->field_name)); \
380                         *out_len = (unsigned)strlen((((rec_t*)rec)->field_name)); \
381                 } else { \
382                         *out_ptr = g_strdup(""); *out_len = 0; } }
383
384 #define UAT_FLD_CSTRING(basename,field_name,title,desc) \
385         {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
386
387 #define UAT_FLD_CSTRING_ISPRINT(basename,field_name,title,desc) \
388         {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_str_isprint,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
389
390 #define UAT_FLD_CSTRING_OTHER(basename,field_name,title,chk,desc) \
391         {#field_name, title, PT_TXTMOD_STRING,{ chk ,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
392
393 /*
394  * FILENAME and DIRECTORYNAME,
395  *    a simple c-string contained in (((rec_t*)rec)->(field_name))
396  */
397 #define UAT_FILENAME_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t)
398
399 /* XXX UAT_FLD_FILENAME is currently unused. */
400 #define UAT_FLD_FILENAME(basename,field_name,title,desc) \
401         {#field_name, title, PT_TXTMOD_FILENAME,{uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
402
403 /*
404  * Both the Qt and GTK+ UIs assume that we're opening a preexisting
405  * file. We might want to split the ..._FILENAME defines into
406  * ..._FILE_OPEN and ..._FILE_SAVE if we ever need to specify a
407  * file that we're creating.
408  */
409 #define UAT_FLD_FILENAME_OTHER(basename,field_name,title,chk,desc) \
410         {#field_name, title, PT_TXTMOD_FILENAME,{chk,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
411
412 #define UAT_DIRECTORYNAME_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t)
413
414 #define UAT_FLD_DIRECTORYNAME(basename,field_name,title,desc) \
415         {#field_name, title, PT_TXTMOD_DIRECTORYNAME,{uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
416
417 /*
418  * OID - just a CSTRING with a specific check routine
419  */
420 #define UAT_FLD_OID(basename,field_name,title,desc) \
421         {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_oid,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
422
423
424 /*
425  * LSTRING MACROS
426  */
427 #define UAT_LSTRING_CB_DEF(basename,field_name,rec_t,ptr_element,len_element) \
428 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
429         char* new_val = uat_unesc(buf,len,&(((rec_t*)rec)->len_element)); \
430         g_free((((rec_t*)rec)->ptr_element)); \
431         (((rec_t*)rec)->ptr_element) = new_val; }\
432 static void basename ## _ ## field_name ## _tostr_cb(void* rec, const char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
433         if (((rec_t*)rec)->ptr_element ) { \
434                 *out_ptr = uat_esc(((rec_t*)rec)->ptr_element, (((rec_t*)rec)->len_element)); \
435                 *out_len = (unsigned)strlen(*out_ptr); \
436         } else { \
437                 *out_ptr = g_strdup(""); \
438                 *out_len = 0; \
439         } \
440 }
441
442 #define UAT_FLD_LSTRING(basename,field_name,title, desc) \
443 {#field_name, title, PT_TXTMOD_STRING,{0,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
444
445
446 /*
447  * BUFFER macros,
448  *    a buffer_ptr contained in (((rec_t*)rec)->(field_name))
449  *    and its len in (((rec_t*)rec)->(len_name))
450  *  XXX: UNTESTED and probably BROKEN
451  */
452 #define UAT_BUFFER_CB_DEF(basename,field_name,rec_t,ptr_element,len_element) \
453 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
454         char* new_buf = len ? (char *)g_memdup(buf,len) : NULL; \
455         g_free((((rec_t*)rec)->ptr_element)); \
456         (((rec_t*)rec)->ptr_element) = new_buf; \
457         (((rec_t*)rec)->len_element) = len; } \
458 static void basename ## _ ## field_name ## _tostr_cb(void* rec, const char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
459         *out_ptr = ((rec_t*)rec)->ptr_element ? (const char*)g_memdup(((rec_t*)rec)->ptr_element,((rec_t*)rec)->len_element) : g_strdup(""); \
460         *out_len = ((rec_t*)rec)->len_element; }
461
462 #define UAT_FLD_BUFFER(basename,field_name,title,desc) \
463         {#field_name, title, PT_TXTMOD_HEXBYTES,{0,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
464
465
466 /*
467  * DEC Macros,
468  *   a decimal number contained in
469  */
470 #define UAT_DEC_CB_DEF(basename,field_name,rec_t) \
471 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
472         char* tmp_str = g_strndup(buf,len); \
473         ((rec_t*)rec)->field_name = (guint)strtol(tmp_str,NULL,10); \
474         g_free(tmp_str); } \
475 static void basename ## _ ## field_name ## _tostr_cb(void* rec, const char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
476         *out_ptr = g_strdup_printf("%d",((rec_t*)rec)->field_name); \
477         *out_len = (unsigned)strlen(*out_ptr); }
478
479 #define UAT_FLD_DEC(basename,field_name,title,desc) \
480         {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_dec,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
481
482 #define UAT_FLD_NONE(basename,field_name,title,desc) \
483         {#field_name, title, PT_TXTMOD_NONE,{uat_fld_chk_num_dec,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
484
485
486 /*
487  * HEX Macros,
488  *   an hexadecimal number contained in
489  */
490 #define UAT_HEX_CB_DEF(basename,field_name,rec_t) \
491 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
492         char* tmp_str = g_strndup(buf,len); \
493         ((rec_t*)rec)->field_name = (guint)strtol(tmp_str,NULL,16); \
494         g_free(tmp_str); } \
495 static void basename ## _ ## field_name ## _tostr_cb(void* rec, const char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
496         *out_ptr = g_strdup_printf("%x",((rec_t*)rec)->field_name); \
497         *out_len = (unsigned)strlen(*out_ptr); }
498
499 #define UAT_FLD_HEX(basename,field_name,title,desc) \
500 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_hex,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
501
502 /*
503  * ENUM macros
504  *  enum_t: name = ((enum_t*)ptr)->strptr
505  *          value = ((enum_t*)ptr)->value
506  *  rec_t:
507  *        value
508  */
509 #define UAT_VS_DEF(basename,field_name,rec_t,default_t,default_val,default_str) \
510 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* vs, const void* UNUSED_PARAMETER(u2)) {\
511         guint i; \
512         char* str = g_strndup(buf,len); \
513         const char* cstr; \
514         ((rec_t*)rec)->field_name = default_val; \
515         for(i=0; ( cstr = ((const value_string*)vs)[i].strptr ) ;i++) { \
516                 if (g_str_equal(cstr,str)) { \
517                         ((rec_t*)rec)->field_name = (default_t)((const value_string*)vs)[i].value; \
518                         g_free(str); \
519                         return; \
520                 } \
521         } \
522         g_free(str); } \
523 static void basename ## _ ## field_name ## _tostr_cb(void* rec, const char** out_ptr, unsigned* out_len, const void* vs, const void* UNUSED_PARAMETER(u2)) {\
524         guint i; \
525         char *str = g_strdup(default_str); \
526         *out_ptr = str; \
527         *out_len = (unsigned)strlen(default_str);\
528         for(i=0;((const value_string*)vs)[i].strptr;i++) { \
529                 if ( ((const value_string*)vs)[i].value == ((rec_t*)rec)->field_name ) { \
530                         g_free(str); \
531                         *out_ptr = g_strdup(((const value_string*)vs)[i].strptr); \
532                         *out_len = (unsigned)strlen(*out_ptr); \
533                         return; \
534                 } \
535         } } \
536
537 #define UAT_VS_CSTRING_DEF(basename,field_name,rec_t,default_val,default_str) \
538 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* vs, const void* UNUSED_PARAMETER(u2)) {\
539         guint i; \
540         char* str = g_strndup(buf,len); \
541         const char* cstr; \
542         ((rec_t*)rec)->field_name = default_val; \
543         for(i=0; ( cstr = ((const value_string*)vs)[i].strptr ) ;i++) { \
544                 if (g_str_equal(cstr,str)) { \
545                   ((rec_t*)rec)->field_name = g_strdup(((const value_string*)vs)[i].strptr); \
546                   g_free(str); \
547                   return; \
548                 } \
549         } \
550         g_free(str);} \
551 static void basename ## _ ## field_name ## _tostr_cb(void* rec, const char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(vs), const void* UNUSED_PARAMETER(u2)) {\
552                 if (((rec_t*)rec)->field_name ) { \
553                         *out_ptr = g_strdup((((rec_t*)rec)->field_name)); \
554                         *out_len = (unsigned)strlen((((rec_t*)rec)->field_name)); \
555                 } else { \
556                         *out_ptr = g_strdup(""); *out_len = 0; } }
557
558 #define UAT_FLD_VS(basename,field_name,title,enum,desc) \
559         {#field_name, title, PT_TXTMOD_ENUM,{uat_fld_chk_enum,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{&(enum),&(enum),&(enum)},&(enum),desc,FLDFILL}
560
561
562 /*
563  * PROTO macros
564  */
565
566 #define UAT_PROTO_DEF(basename, field_name, dissector_field, name_field, rec_t) \
567 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
568         if (len) { \
569                 gchar *tmp = g_strndup(buf,len); \
570                 ((rec_t*)rec)->name_field = g_ascii_strdown(tmp, -1); \
571                 g_free(tmp); \
572                 g_strchug(((rec_t*)rec)->name_field); \
573                 ((rec_t*)rec)->dissector_field = find_dissector(((rec_t*)rec)->name_field); \
574         } else { \
575                 ((rec_t*)rec)->dissector_field = find_dissector("data"); \
576                 ((rec_t*)rec)->name_field = NULL; \
577                 } } \
578 static void basename ## _ ## field_name ## _tostr_cb(void* rec, const char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
579         if ( ((rec_t*)rec)->name_field ) { \
580                 *out_ptr = g_strdup((((rec_t*)rec)->name_field)); \
581                 *out_len = (unsigned)strlen(*out_ptr); \
582         } else { \
583                 *out_ptr = g_strdup(""); *out_len = 0; } }
584
585
586 #define UAT_FLD_PROTO(basename,field_name,title,desc) \
587         {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_proto,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
588
589 /*
590  * RANGE macros
591  */
592
593 #define UAT_RANGE_CB_DEF(basename,field_name,rec_t) \
594 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, guint len, const void* UNUSED_PARAMETER(u1), const void* u2) {\
595         char* rng = g_strndup(buf,len);\
596                 range_convert_str(&(((rec_t*)rec)->field_name), rng,GPOINTER_TO_UINT(u2)); \
597                 g_free(rng); \
598         } \
599 static void basename ## _ ## field_name ## _tostr_cb(void* rec, const char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
600         if ( ((rec_t*)rec)->field_name ) { \
601                 *out_ptr = range_convert_range(NULL, ((rec_t*)rec)->field_name); \
602                 *out_len = (unsigned)strlen(*out_ptr); \
603         } else { \
604                 *out_ptr = g_strdup(""); *out_len = 0; } }
605
606
607 #define UAT_FLD_RANGE(basename,field_name,title,max,desc) \
608         {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_range,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},\
609           {0,0,0},GUINT_TO_POINTER(max),desc,FLDFILL}
610
611 #ifdef __cplusplus
612 }
613 #endif /* __cplusplus */
614
615 #endif /* __UAT_H__ */