attr_dissector_fn_t
[wireshark-sm.git] / epan / uat.h
blob66189b51dc174c98ca59311b83a471420012064a
1 /** @file
3 * User Accessible Tables
4 * Maintain an array of user accessible data structures
6 * (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 2001 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 #ifndef __UAT_H__
16 #define __UAT_H__
18 #include <stdlib.h>
20 #include "ws_symbol_export.h"
21 #include <wsutil/strtoi.h>
23 #ifdef __cplusplus
24 extern "C" {
25 #endif /* __cplusplus */
28 * UAT maintains a dynamically allocated table accessible to the user
29 * via a file and/or via GUI preference dialogs.
31 * The file is read from and written in the personal configuration directory. If
32 * there is no such file, defaults will be loaded from the global data
33 * directory.
35 * The behaviour of the table is controlled by a series of callbacks which
36 * the caller (e.g. a dissector) must provide.
38 * BEWARE that the user can change an UAT at (almost) any time (via the GUI).
39 * That is, pointers to records in an UAT are valid only during the call
40 * to the function that obtains them (do not store pointers to these records).
41 * The records contents are only guaranteed to be valid in the post_update_cb
42 * function. (Implementation detail: currently a race condition is possible
43 * where the UAT consumer (dissector code) tries to use the UAT while the GUI
44 * user frees a record resulting in use-after-free. This is not ideal and might
45 * be fixed later.)
47 * UATs are meant for short tables of user data (passwords and such), there is
48 * no quick access, you must iterate through them each time to fetch the record
49 * you are looking for.
51 * Only users via GUI or editing the file can add/remove records, your
52 * (dissector) code cannot.
55 /* obscure data type to handle an uat */
56 typedef struct epan_uat uat_t;
57 /********************************************
58 * Callbacks:
59 * these instruct uat on how to deal with user info and data in records
60 ********************************************/
62 /********
63 * Callbacks dealing with the entire table
64 ********/
67 * Post-Update CB
69 * To be called by the GUI code after to the table has being edited.
70 * Will be called once the user clicks the Apply or OK button
71 * optional
73 typedef void (*uat_post_update_cb_t)(void);
76 /********
77 * Callbacks dealing with records (these deal with entire records)
78 ********/
80 /**
81 * Copy CB
82 * copy(dest, source, len)
84 * Used to duplicate the contents of one record to another.
85 * Optional, memcpy will be used if not given.
87 typedef void* (*uat_copy_cb_t)(void *dest, const void *source, size_t len);
89 /**
90 * Free CB
91 * free(record)
93 * Destroy the contents of a record, possibly freeing some fields.
94 * Do not free the container itself, this memory is owned by the UAT core.
95 * Optional if the record contains no pointers that need to be freed.
97 typedef void (*uat_free_cb_t)(void *record);
99 /**
100 * Reset DB
102 * Used to free resources associated with a UAT loaded from file (e.g. post_update_cb)
103 * Optional.
105 typedef void (*uat_reset_cb_t)(void);
108 * Update CB
109 * update(record,&error)
111 * Validates the contents of the record contents, to be called after any record
112 * fields had been updated (either from file or after modifications in the GUI).
114 * Optional, the record will be considered valid if the callback is omitted.
115 * It must return true if the contents are considered valid and false otherwise
116 * in which case the failure reason is set in 'error'. The error string will be
117 * freed by g_free.
119 * XXX: This should only validate the record. Any changes to the record
120 * made here will *not* be persistent if the UAT is saved again, unless
121 * the same changes are also done to a new record created by the copy cb,
122 * e.g. by having the the copy callback call this.
123 * It should probably be made into a const void* to make that clear.
125 typedef bool (*uat_update_cb_t)(void *record, char **error);
128 /*******
129 * Callbacks for single fields (these deal with single values)
130 * the caller should provide one of these for every field!
131 ********/
134 * Check CB
135 * chk(record, ptr, len, chk_data, fld_data, &error)
137 * given an input string (ptr, len) checks if the value is OK for a field in the record.
138 * it will return true if OK or else
139 * it will return false and set *error to inform the user on what's
140 * wrong with the given input
141 * The error string must be allocated with g_malloc() or
142 * a routine that calls it.
143 * optional, if not given any input is considered OK and the set cb will be called
145 typedef bool (*uat_fld_chk_cb_t)(void *record, const char *ptr, unsigned len, const void *chk_data, const void *fld_data, char **error);
148 * Set Field CB
149 * set(record, ptr, len, set_data, fld_data)
151 * given an input string (ptr, len) sets the value of a field in the record,
152 * it is mandatory
154 typedef void (*uat_fld_set_cb_t)(void *record, const char *ptr, unsigned len, const void *set_data, const void *fld_data);
157 * Convert-to-string CB
158 * tostr(record, &out_ptr, &out_len, tostr_data, fld_data)
160 * given a record returns a string representation of the field
161 * mandatory
163 typedef void (*uat_fld_tostr_cb_t)(void *record, char **out_ptr, unsigned *out_len, const void *tostr_data, const void *fld_data);
165 /***********
166 * Text Mode
168 * used for file and dialog representation of fields in columns,
169 * when the file is read it modifies the way the value is passed back to the fld_set_cb
170 * (see definition bellow for description)
171 ***********/
173 typedef enum _uat_text_mode_t {
174 PT_TXTMOD_NONE,
175 /* not used */
177 PT_TXTMOD_STRING,
179 file:
180 reads:
181 ,"\x20\x00\x30", as " \00",3 ("space nil zero" of length 3)
182 ,"", as "",0
183 ,, as NULL,0
184 writes:
185 ,"\x20\x30\x00\x20", for " 0\0 ",4
186 ,"", for *, 0
187 ,, for NULL, *
188 dialog:
189 accepts \x?? and other escapes
190 gets "",0 on empty string
192 PT_TXTMOD_HEXBYTES,
194 file:
195 reads:
196 ,A1b2C3d4, as "\xa1\xb2\xc3\xd4",4
197 ,, as NULL,0
198 writes:
199 ,, on NULL, *
200 ,a1b2c3d4, on "\xa1\xb2\xc3\xd4",4
201 dialog:
202 interprets the following input ... as ...:
203 "a1b2c3d4" as "\xa1\xb2\xc3\xd4",4
204 "a1 b2:c3d4" as "\xa1\xb2\xc3\xd4",4
205 "" as NULL,0
206 "invalid" as NULL,3
207 "a1b" as NULL, 1
209 PT_TXTMOD_ENUM,
210 /* Read/Writes/displays the string value (not number!) */
211 PT_TXTMOD_DISSECTOR,
212 /* Shows a combobox of dissectors */
214 PT_TXTMOD_COLOR,
215 /* Reads/Writes/display color in #RRGGBB format */
217 PT_TXTMOD_FILENAME,
218 /* processed like a PT_TXTMOD_STRING, but shows a filename dialog */
219 PT_TXTMOD_DIRECTORYNAME,
220 /* processed like a PT_TXTMOD_STRING, but shows a directory dialog */
221 PT_TXTMOD_DISPLAY_FILTER,
222 /* processed like a PT_TXTMOD_STRING, but verifies display filter */
223 PT_TXTMOD_PROTO_FIELD,
224 /* processed like a PT_TXTMOD_STRING, but verifies protocol field name (e.g tcp.flags.syn) */
225 PT_TXTMOD_BOOL
226 /* Displays a checkbox for value */
227 } uat_text_mode_t;
230 * Fields
234 typedef struct _uat_field_t {
235 const char* name;
236 const char* title;
237 uat_text_mode_t mode;
239 struct {
240 uat_fld_chk_cb_t chk;
241 uat_fld_set_cb_t set;
242 uat_fld_tostr_cb_t tostr;
243 } cb;
245 struct {
246 const void* chk;
247 const void* set;
248 const void* tostr;
249 } cbdata;
251 const void* fld_data;
253 const char* desc;
254 struct _fld_data_t* priv;
255 } uat_field_t;
257 #define FLDFILL NULL
258 #define UAT_END_FIELDS {NULL,NULL,PT_TXTMOD_NONE,{0,0,0},{0,0,0},0,0,FLDFILL}
261 * Flags to indicate what the settings in this UAT affect.
262 * This is used when UATs are changed interactively, to indicate what needs
263 * to be redone when the UAT is changed.
265 * UAT_AFFECTS_FIELDS does *not* trigger a redissection, so usually one
266 * will also want UAT_AFFECTS_DISSECTION. A rare exception is changing
267 * the defined dfilter macros.
269 #define UAT_AFFECTS_DISSECTION 0x00000001 /* affects packet dissection */
270 #define UAT_AFFECTS_FIELDS 0x00000002 /* affects what named fields exist */
272 /** Create a new UAT.
274 * @param name The name of the table
275 * @param size The size of the structure
276 * @param filename The filename to be used (either in userdir or datadir)
277 * @param from_profile true if profile directory to be used
278 * @param data_ptr Although a void*, this is really a pointer to a null terminated array of pointers to the data
279 * @param num_items_ptr A pointer with number of items
280 * @param flags flags indicating what this UAT affects
281 * @param help A pointer to help text
282 * @param copy_cb A function that copies the data in the struct
283 * @param update_cb Will be called when a record is updated
284 * @param free_cb Will be called to destroy a struct in the dataset
285 * @param post_update_cb Will be called once the user clicks the Apply or OK button
286 * @param reset_cb Will be called to destroy internal data
287 * @param flds_array A pointer to an array of uat_field_t structs
289 * @return A freshly-allocated and populated uat_t struct.
291 WS_DLL_PUBLIC
292 uat_t* uat_new(const char* name,
293 size_t size,
294 const char* filename,
295 bool from_profile,
296 void* data_ptr,
297 unsigned* num_items_ptr,
298 unsigned flags,
299 const char* help,
300 uat_copy_cb_t copy_cb,
301 uat_update_cb_t update_cb,
302 uat_free_cb_t free_cb,
303 uat_post_update_cb_t post_update_cb,
304 uat_reset_cb_t reset_cb,
305 uat_field_t* flds_array);
307 /** Free and deregister a single UAT.
310 WS_DLL_PUBLIC
311 void uat_destroy(uat_t *uat);
313 /** Cleanup all UATs.
316 void uat_cleanup(void);
318 /** Populate a UAT using its file.
320 * @param uat_in Pointer to a uat. Must not be NULL.
321 * @param filename Filename to load, NULL to fetch from current profile.
322 * @param err Upon failure, points to an error string.
324 * @return true on success, false on failure.
326 WS_DLL_PUBLIC
327 bool uat_load(uat_t* uat_in, const char *filename, char** err);
329 /** Create or update a single UAT entry using a string.
331 * @param uat_in Pointer to a uat. Must not be NULL.
332 * @param entry The string representation of the entry. Format must match
333 * what's written to the uat's output file.
334 * @param err Upon failure, points to an error string.
336 * @return true on success, false on failure.
338 bool uat_load_str(uat_t* uat_in, const char* entry, char** err);
340 /** Given a UAT name or filename, find its pointer.
342 * @param name The name or filename of the uat
344 * @return A pointer to the uat on success, NULL on failure.
346 uat_t *uat_find(char *name);
348 WS_DLL_PUBLIC
349 uat_t* uat_get_table_by_name(const char* name);
352 * Provide default field values for a UAT.
354 * This can be used to provide forward compatibility when fields are added
355 * to a UAT.
357 * @param uat_in Pointer to a uat. Must not be NULL.
358 * @param default_values An array of strings with default values. Must
359 * be the same length as flds_array. Individual elements can be NULL,
360 * and can be used to distinguish between mandatory and optional fields,
361 * e.g. { NULL, NULL, NULL, "default value (optional)" }
362 * @todo Use this to provide default values for empty tables.
364 WS_DLL_PUBLIC
365 void uat_set_default_values(uat_t *uat_in, const char *default_values[]);
368 * Some common uat_fld_chk_cbs
370 WS_DLL_PUBLIC
371 bool uat_fld_chk_str(void*, const char*, unsigned, const void*, const void*, char** err);
372 bool uat_fld_chk_oid(void*, const char*, unsigned, const void*, const void*, char** err);
373 WS_DLL_PUBLIC
374 bool uat_fld_chk_proto(void*, const char*, unsigned, const void*, const void*, char** err);
375 WS_DLL_PUBLIC
376 bool uat_fld_chk_num_dec(void*, const char*, unsigned, const void*, const void*, char** err);
377 WS_DLL_PUBLIC
378 bool uat_fld_chk_num_dec64(void*, const char*, unsigned, const void*, const void*, char** err);
379 WS_DLL_PUBLIC
380 bool uat_fld_chk_num_hex(void*, const char*, unsigned, const void*, const void*, char** err);
381 WS_DLL_PUBLIC
382 bool uat_fld_chk_num_hex64(void*, const char*, unsigned, const void*, const void*, char** err);
383 WS_DLL_PUBLIC
384 bool uat_fld_chk_num_signed_dec(void*, const char*, unsigned, const void*, const void*, char** err);
385 WS_DLL_PUBLIC
386 bool uat_fld_chk_num_signed_dec64(void*, const char*, unsigned, const void*, const void*, char** err);
387 WS_DLL_PUBLIC
388 bool uat_fld_chk_bool(void*, const char*, unsigned, const void*, const void*, char** err);
389 WS_DLL_PUBLIC
390 bool uat_fld_chk_enum(void*, const char*, unsigned, const void*, const void*, char**);
391 WS_DLL_PUBLIC
392 bool uat_fld_chk_range(void*, const char*, unsigned, const void*, const void*, char**);
393 WS_DLL_PUBLIC
394 bool uat_fld_chk_color(void*, const char*, unsigned, const void*, const void*, char**);
396 typedef void (*uat_cb_t)(void* uat,void* user_data);
397 WS_DLL_PUBLIC
398 void uat_foreach_table(uat_cb_t cb,void* user_data);
399 void uat_unload_all(void);
401 char* uat_undquote(const char* si, unsigned in_len, unsigned* len_p);
402 char* uat_unbinstring(const char* si, unsigned in_len, unsigned* len_p);
403 char* uat_unesc(const char* si, unsigned in_len, unsigned* len_p);
404 char* uat_esc(const char* buf, unsigned len);
406 /* Some strings entirely made of ... already declared */
408 WS_DLL_PUBLIC
409 bool uat_fld_chk_str_isprint(void*, const char*, unsigned, const void*, const void*, char**);
411 WS_DLL_PUBLIC
412 bool uat_fld_chk_str_isalpha(void*, const char*, unsigned, const void*, const void*, char**);
414 WS_DLL_PUBLIC
415 bool uat_fld_chk_str_isalnum(void*, const char*, unsigned, const void*, const void*, char**);
417 WS_DLL_PUBLIC
418 bool uat_fld_chk_str_isdigit(void*, const char*, unsigned, const void*, const void*, char**);
420 WS_DLL_PUBLIC
421 bool uat_fld_chk_str_isxdigit(void*, const char*, unsigned, const void*, const void*, char**);
425 * Macros
426 * to define basic uat_fld_set_cbs, uat_fld_tostr_cbs
427 * for those elements in uat_field_t array
430 #ifdef __cplusplus
431 #define UNUSED_PARAMETER(n)
432 #else
433 #define UNUSED_PARAMETER(n) n _U_
434 #endif
437 * CSTRING macros,
438 * a simple c-string contained in (((rec_t*)rec)->(field_name))
440 #define UAT_CSTRING_CB_DEF(basename,field_name,rec_t) \
441 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
442 char* new_buf = g_strndup(buf,len); \
443 g_free((((rec_t*)rec)->field_name)); \
444 (((rec_t*)rec)->field_name) = new_buf; } \
445 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
446 if (((rec_t*)rec)->field_name ) { \
447 *out_ptr = g_strdup((((rec_t*)rec)->field_name)); \
448 *out_len = (unsigned)strlen((((rec_t*)rec)->field_name)); \
449 } else { \
450 *out_ptr = g_strdup(""); *out_len = 0; \
453 #define UAT_FLD_CSTRING(basename,field_name,title,desc) \
454 {#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}
456 #define UAT_FLD_CSTRING_ISPRINT(basename,field_name,title,desc) \
457 {#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}
459 #define UAT_FLD_CSTRING_OTHER(basename,field_name,title,chk,desc) \
460 {#field_name, title, PT_TXTMOD_STRING,{ chk ,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
463 * FILENAME and DIRECTORYNAME,
464 * a simple c-string contained in (((rec_t*)rec)->(field_name))
466 #define UAT_FILENAME_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t)
468 /* XXX UAT_FLD_FILENAME is currently unused. */
469 #define UAT_FLD_FILENAME(basename,field_name,title,desc) \
470 {#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}
473 * Both the Qt and GTK+ UIs assume that we're opening a preexisting
474 * file. We might want to split the ..._FILENAME defines into
475 * ..._FILE_OPEN and ..._FILE_SAVE if we ever need to specify a
476 * file that we're creating.
478 #define UAT_FLD_FILENAME_OTHER(basename,field_name,title,chk,desc) \
479 {#field_name, title, PT_TXTMOD_FILENAME,{chk,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
481 #define UAT_DIRECTORYNAME_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t)
483 #define UAT_FLD_DIRECTORYNAME(basename,field_name,title,desc) \
484 {#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}
487 * DISPLAY_FILTER,
488 * a simple c-string contained in (((rec_t*)rec)->(field_name))
490 #define UAT_DISPLAY_FILTER_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t)
492 #define UAT_FLD_DISPLAY_FILTER(basename,field_name,title,desc) \
493 {#field_name, title, PT_TXTMOD_DISPLAY_FILTER, {uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
496 * PROTO_FIELD,
497 * a simple c-string contained in (((rec_t*)rec)->(field_name))
499 #define UAT_PROTO_FIELD_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t)
501 #define UAT_FLD_PROTO_FIELD(basename,field_name,title,desc) \
502 {#field_name, title, PT_TXTMOD_PROTO_FIELD, {uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
505 * OID - just a CSTRING with a specific check routine
507 #define UAT_FLD_OID(basename,field_name,title,desc) \
508 {#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}
512 * LSTRING MACROS
514 #define UAT_LSTRING_CB_DEF(basename,field_name,rec_t,ptr_element,len_element) \
515 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
516 char* new_val = uat_unesc(buf,len,&(((rec_t*)rec)->len_element)); \
517 g_free((((rec_t*)rec)->ptr_element)); \
518 (((rec_t*)rec)->ptr_element) = new_val; } \
519 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
520 if (((rec_t*)rec)->ptr_element ) { \
521 *out_ptr = uat_esc(((rec_t*)rec)->ptr_element, (((rec_t*)rec)->len_element)); \
522 *out_len = (unsigned)strlen(*out_ptr); \
523 } else { \
524 *out_ptr = g_strdup(""); \
525 *out_len = 0; \
528 #define UAT_FLD_LSTRING(basename,field_name,title, desc) \
529 {#field_name, title, PT_TXTMOD_STRING,{0,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
533 * BUFFER macros,
534 * a buffer_ptr contained in (((rec_t*)rec)->(field_name))
535 * and its len in (((rec_t*)rec)->(len_name))
537 #define UAT_BUFFER_CB_DEF(basename,field_name,rec_t,ptr_element,len_element) \
538 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
539 unsigned char* new_buf = len ? (unsigned char *)g_memdup2(buf,len) : NULL; \
540 g_free((((rec_t*)rec)->ptr_element)); \
541 (((rec_t*)rec)->ptr_element) = new_buf; \
542 (((rec_t*)rec)->len_element) = len; } \
543 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
544 *out_ptr = ((rec_t*)rec)->ptr_element ? (char*)g_memdup2(((rec_t*)rec)->ptr_element,((rec_t*)rec)->len_element) : g_strdup(""); \
545 *out_len = ((rec_t*)rec)->len_element; }
547 #define UAT_FLD_BUFFER(basename,field_name,title,desc) \
548 {#field_name, title, PT_TXTMOD_HEXBYTES,{0,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
552 * DEC Macros,
553 * an unsigned decimal number contained in (((rec_t*)rec)->(field_name))
555 #define UAT_DEC_CB_DEF(basename,field_name,rec_t) \
556 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
557 char* tmp_str = g_strndup(buf,len); \
558 ws_strtou32(tmp_str, NULL, &((rec_t*)rec)->field_name); \
559 g_free(tmp_str); } \
560 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
561 *out_ptr = ws_strdup_printf("%u",((rec_t*)rec)->field_name); \
562 *out_len = (unsigned)strlen(*out_ptr); }
564 #define UAT_FLD_DEC(basename,field_name,title,desc) \
565 {#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}
568 * an unsigned 64bit decimal number contained in (((rec_t*)rec)->(field_name))
570 #define UAT_DEC64_CB_DEF(basename,field_name,rec_t) \
571 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
572 char* tmp_str = g_strndup(buf,len); \
573 ws_strtou64(tmp_str, NULL, &((rec_t*)rec)->field_name); \
574 g_free(tmp_str); } \
575 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
576 *out_ptr = ws_strdup_printf("%" PRIu64,((rec_t*)rec)->field_name); \
577 *out_len = (unsigned)strlen(*out_ptr); }
579 #define UAT_FLD_DEC64(basename,field_name,title,desc) \
580 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_dec64,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
583 * a *signed* decimal number contained in (((rec_t*)rec)->(field_name))
585 #define UAT_SIGNED_DEC_CB_DEF(basename,field_name,rec_t) \
586 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
587 char* tmp_str = g_strndup(buf,len); \
588 ws_strtoi32(tmp_str, NULL, &((rec_t*)rec)->field_name); \
589 g_free(tmp_str); } \
590 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
591 *out_ptr = ws_strdup_printf("%d",((rec_t*)rec)->field_name); \
592 *out_len = (unsigned)strlen(*out_ptr); }
594 #define UAT_FLD_SIGNED_DEC(basename,field_name,title,desc) \
595 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_signed_dec,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
598 * and a *signed* 64bit decimal number contained in (((rec_t*)rec)->(field_name))
600 #define UAT_SIGNED_DEC64_CB_DEF(basename,field_name,rec_t) \
601 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
602 char* tmp_str = g_strndup(buf,len); \
603 ws_strtoi64(tmp_str, NULL, &((rec_t*)rec)->field_name); \
604 g_free(tmp_str); } \
605 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
606 *out_ptr = ws_strdup_printf("%" PRId64,((rec_t*)rec)->field_name); \
607 *out_len = (unsigned)strlen(*out_ptr); }
609 #define UAT_FLD_SIGNED_DEC64(basename,field_name,title,desc) \
610 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_signed_dec64,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
612 #define UAT_FLD_NONE(basename,field_name,title,desc) \
613 {#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}
617 * HEX Macros,
618 * an unsigned hexadecimal number contained in (((rec_t*)rec)->(field_name))
620 #define UAT_HEX_CB_DEF(basename,field_name,rec_t) \
621 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
622 char* tmp_str = g_strndup(buf,len); \
623 ws_hexstrtou32(tmp_str, NULL, &((rec_t*)rec)->field_name); \
624 g_free(tmp_str); } \
625 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
626 *out_ptr = ws_strdup_printf("%x",((rec_t*)rec)->field_name); \
627 *out_len = (unsigned)strlen(*out_ptr); }
629 #define UAT_FLD_HEX(basename,field_name,title,desc) \
630 {#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}
633 * HEX Macros for 64bit,
634 * an unsigned long long hexadecimal number contained in (((rec_t*)rec)->(field_name))
636 #define UAT_HEX64_CB_DEF(basename,field_name,rec_t) \
637 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
638 char* tmp_str = g_strndup(buf,len); \
639 ws_hexstrtou64(tmp_str, NULL, &((rec_t*)rec)->field_name); \
640 g_free(tmp_str); } \
641 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
642 *out_ptr = ws_strdup_printf("%" PRIx64,((rec_t*)rec)->field_name); \
643 *out_len = (unsigned)strlen(*out_ptr); }
645 #define UAT_FLD_HEX64(basename,field_name,title,desc) \
646 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_hex64,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
649 * BOOL Macros,
650 * an boolean value contained in (((rec_t*)rec)->(field_name))
652 * Write "TRUE" or "FALSE" for backwards compatibility with pre-4.4
653 * versions that expect that capitalization.
655 #define UAT_BOOL_CB_DEF(basename,field_name,rec_t) \
656 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
657 char* tmp_str = g_strndup(buf,len); \
658 if (tmp_str && g_ascii_strcasecmp(tmp_str, "true") == 0) \
659 ((rec_t*)rec)->field_name = 1; \
660 else \
661 ((rec_t*)rec)->field_name = 0; \
662 g_free(tmp_str); } \
663 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
664 *out_ptr = ws_strdup_printf("%s",((rec_t*)rec)->field_name ? "TRUE" : "FALSE"); \
665 *out_len = (unsigned)strlen(*out_ptr); }
667 #define UAT_FLD_BOOL(basename,field_name,title,desc) \
668 {#field_name, title, PT_TXTMOD_BOOL,{uat_fld_chk_bool,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
671 * ENUM macros
672 * enum_t: name = ((enum_t*)ptr)->strptr
673 * value = ((enum_t*)ptr)->value
674 * rec_t:
675 * value
677 #define UAT_VS_DEF(basename,field_name,rec_t,default_t,default_val,default_str) \
678 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* vs, const void* UNUSED_PARAMETER(u2)) {\
679 unsigned i; \
680 char* str = g_strndup(buf,len); \
681 const char* cstr; \
682 ((rec_t*)rec)->field_name = default_val; \
683 for(i=0; ( cstr = ((const value_string*)vs)[i].strptr ) ;i++) { \
684 if (g_str_equal(cstr,str)) { \
685 ((rec_t*)rec)->field_name = (default_t)((const value_string*)vs)[i].value; \
686 g_free(str); \
687 return; \
690 g_free(str); } \
691 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* vs, const void* UNUSED_PARAMETER(u2)) {\
692 unsigned i; \
693 for(i=0;((const value_string*)vs)[i].strptr;i++) { \
694 if ( ((const value_string*)vs)[i].value == ((rec_t*)rec)->field_name ) { \
695 *out_ptr = g_strdup(((const value_string*)vs)[i].strptr); \
696 *out_len = (unsigned)strlen(*out_ptr); \
697 return; \
700 *out_ptr = g_strdup(default_str); \
701 *out_len = (unsigned)strlen(default_str); }
703 #define UAT_VS_CSTRING_DEF(basename,field_name,rec_t,default_val,default_str) \
704 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* vs, const void* UNUSED_PARAMETER(u2)) {\
705 unsigned i; \
706 char* str = g_strndup(buf,len); \
707 const char* cstr; \
708 ((rec_t*)rec)->field_name = default_val; \
709 for(i=0; ( cstr = ((const value_string*)vs)[i].strptr ) ;i++) { \
710 if (g_str_equal(cstr,str)) { \
711 ((rec_t*)rec)->field_name = g_strdup(((const value_string*)vs)[i].strptr); \
712 g_free(str); \
713 return; \
716 g_free(str);} \
717 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(vs), const void* UNUSED_PARAMETER(u2)) {\
718 if (((rec_t*)rec)->field_name ) { \
719 *out_ptr = g_strdup((((rec_t*)rec)->field_name)); \
720 *out_len = (unsigned)strlen((((rec_t*)rec)->field_name)); \
721 } else { \
722 *out_ptr = g_strdup(""); *out_len = 0; } }
724 #define UAT_FLD_VS(basename,field_name,title,enum,desc) \
725 {#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}
729 * Color Macros,
730 * an #RRGGBB color value contained in (((rec_t*)rec)->(field_name))
732 #define UAT_COLOR_CB_DEF(basename,field_name,rec_t) \
733 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
734 if (len < 1) { \
735 ((rec_t*)rec)->field_name = 0; \
736 return; \
738 char* tmp_str = g_strndup(buf+1,len-1); \
739 ((rec_t*)rec)->field_name = (unsigned)strtol(tmp_str,NULL,16); \
740 g_free(tmp_str); } \
741 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
742 *out_ptr = ws_strdup_printf("#%06X",((rec_t*)rec)->field_name); \
743 *out_len = (unsigned)strlen(*out_ptr); }
745 #define UAT_FLD_COLOR(basename,field_name,title,desc) \
746 {#field_name, title, PT_TXTMOD_COLOR,{uat_fld_chk_color,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
750 * DISSECTOR macros
753 #define UAT_DISSECTOR_DEF(basename, field_name, dissector_field, name_field, rec_t) \
754 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
755 if (len) { \
756 ((rec_t*)rec)->name_field = g_strndup(buf, len); \
757 g_strstrip(((rec_t*)rec)->name_field); \
758 ((rec_t*)rec)->dissector_field = find_dissector(((rec_t*)rec)->name_field); \
759 } else { \
760 ((rec_t*)rec)->dissector_field = find_dissector("data"); \
761 ((rec_t*)rec)->name_field = NULL; \
762 } } \
763 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
764 if ( ((rec_t*)rec)->name_field ) { \
765 *out_ptr = g_strdup((((rec_t*)rec)->name_field)); \
766 *out_len = (unsigned)strlen(*out_ptr); \
767 } else { \
768 *out_ptr = g_strdup(""); *out_len = 0; \
772 #define UAT_FLD_DISSECTOR(basename,field_name,title,desc) \
773 {#field_name, title, PT_TXTMOD_DISSECTOR,{uat_fld_chk_proto,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
775 #define UAT_FLD_DISSECTOR_OTHER(basename,field_name,title,chk,desc) \
776 {#field_name, title, PT_TXTMOD_DISSECTOR,{chk,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
779 * RANGE macros
782 #define UAT_RANGE_CB_DEF(basename,field_name,rec_t) \
783 static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* u2) {\
784 char* rng = g_strndup(buf,len);\
785 range_convert_str(NULL, &(((rec_t*)rec)->field_name), rng,GPOINTER_TO_UINT(u2)); \
786 g_free(rng); \
788 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
789 if ( ((rec_t*)rec)->field_name ) { \
790 *out_ptr = range_convert_range(NULL, ((rec_t*)rec)->field_name); \
791 *out_len = (unsigned)strlen(*out_ptr); \
792 } else { \
793 *out_ptr = g_strdup(""); *out_len = 0; \
797 #define UAT_FLD_RANGE(basename,field_name,title,max,desc) \
798 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_range,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},\
799 {0,0,0},GUINT_TO_POINTER(max),desc,FLDFILL}
801 #ifdef __cplusplus
803 #endif /* __cplusplus */
805 #endif /* __UAT_H__ */
808 * Editor modelines
810 * Local Variables:
811 * c-basic-offset: 4
812 * tab-width: 8
813 * indent-tabs-mode: nil
814 * End:
816 * ex: set shiftwidth=4 tabstop=8 expandtab:
817 * :indentSize=4:tabSize=8:noTabs=true: