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
20 #include "ws_symbol_export.h"
21 #include <wsutil/strtoi.h>
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
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
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 /********************************************
59 * these instruct uat on how to deal with user info and data in records
60 ********************************************/
63 * Callbacks dealing with the entire table
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
73 typedef void (*uat_post_update_cb_t
)(void);
77 * Callbacks dealing with records (these deal with entire records)
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
);
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
);
102 * Used to free resources associated with a UAT loaded from file (e.g. post_update_cb)
105 typedef void (*uat_reset_cb_t
)(void);
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
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
);
129 * Callbacks for single fields (these deal with single values)
130 * the caller should provide one of these for every field!
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
);
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,
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
163 typedef void (*uat_fld_tostr_cb_t
)(void *record
, char **out_ptr
, unsigned *out_len
, const void *tostr_data
, const void *fld_data
);
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)
173 typedef enum _uat_text_mode_t
{
181 ,"\x20\x00\x30", as " \00",3 ("space nil zero" of length 3)
185 ,"\x20\x30\x00\x20", for " 0\0 ",4
189 accepts \x?? and other escapes
190 gets "",0 on empty string
196 ,A1b2C3d4, as "\xa1\xb2\xc3\xd4",4
200 ,a1b2c3d4, on "\xa1\xb2\xc3\xd4",4
202 interprets the following input ... as ...:
203 "a1b2c3d4" as "\xa1\xb2\xc3\xd4",4
204 "a1 b2:c3d4" as "\xa1\xb2\xc3\xd4",4
210 /* Read/Writes/displays the string value (not number!) */
212 /* Shows a combobox of dissectors */
215 /* Reads/Writes/display color in #RRGGBB format */
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) */
226 /* Displays a checkbox for value */
234 typedef struct _uat_field_t
{
237 uat_text_mode_t mode
;
240 uat_fld_chk_cb_t chk
;
241 uat_fld_set_cb_t set
;
242 uat_fld_tostr_cb_t tostr
;
251 const void* fld_data
;
254 struct _fld_data_t
* priv
;
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.
292 uat_t
* uat_new(const char* name
,
294 const char* filename
,
297 unsigned* num_items_ptr
,
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.
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.
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
);
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
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.
365 void uat_set_default_values(uat_t
*uat_in
, const char *default_values
[]);
368 * Some common uat_fld_chk_cbs
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
);
374 bool uat_fld_chk_proto(void*, const char*, unsigned, const void*, const void*, char** err
);
376 bool uat_fld_chk_num_dec(void*, const char*, unsigned, const void*, const void*, char** err
);
378 bool uat_fld_chk_num_dec64(void*, const char*, unsigned, const void*, const void*, char** err
);
380 bool uat_fld_chk_num_hex(void*, const char*, unsigned, const void*, const void*, char** err
);
382 bool uat_fld_chk_num_hex64(void*, const char*, unsigned, const void*, const void*, char** err
);
384 bool uat_fld_chk_num_signed_dec(void*, const char*, unsigned, const void*, const void*, char** err
);
386 bool uat_fld_chk_num_signed_dec64(void*, const char*, unsigned, const void*, const void*, char** err
);
388 bool uat_fld_chk_bool(void*, const char*, unsigned, const void*, const void*, char** err
);
390 bool uat_fld_chk_enum(void*, const char*, unsigned, const void*, const void*, char**);
392 bool uat_fld_chk_range(void*, const char*, unsigned, const void*, const void*, char**);
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
);
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 */
409 bool uat_fld_chk_str_isprint(void*, const char*, unsigned, const void*, const void*, char**);
412 bool uat_fld_chk_str_isalpha(void*, const char*, unsigned, const void*, const void*, char**);
415 bool uat_fld_chk_str_isalnum(void*, const char*, unsigned, const void*, const void*, char**);
418 bool uat_fld_chk_str_isdigit(void*, const char*, unsigned, const void*, const void*, char**);
421 bool uat_fld_chk_str_isxdigit(void*, const char*, unsigned, const void*, const void*, char**);
426 * to define basic uat_fld_set_cbs, uat_fld_tostr_cbs
427 * for those elements in uat_field_t array
431 #define UNUSED_PARAMETER(n)
433 #define UNUSED_PARAMETER(n) n _U_
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)); \
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}
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}
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}
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); \
524 *out_ptr = g_strdup(""); \
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}
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}
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); \
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); \
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); \
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); \
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}
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); \
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); \
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}
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; \
661 ((rec_t*)rec)->field_name = 0; \
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}
672 * enum_t: name = ((enum_t*)ptr)->strptr
673 * value = ((enum_t*)ptr)->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)) {\
680 char* str = g_strndup(buf,len); \
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; \
691 static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* vs, const void* UNUSED_PARAMETER(u2)) {\
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); \
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)) {\
706 char* str = g_strndup(buf,len); \
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); \
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)); \
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}
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)) {\
735 ((rec_t*)rec)->field_name = 0; \
738 char* tmp_str = g_strndup(buf+1,len-1); \
739 ((rec_t*)rec)->field_name = (unsigned)strtol(tmp_str,NULL,16); \
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}
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)) {\
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); \
760 ((rec_t*)rec)->dissector_field = find_dissector("data"); \
761 ((rec_t*)rec)->name_field = NULL; \
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); \
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}
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)); \
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); \
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}
803 #endif /* __cplusplus */
805 #endif /* __UAT_H__ */
813 * indent-tabs-mode: nil
816 * ex: set shiftwidth=4 tabstop=8 expandtab:
817 * :indentSize=4:tabSize=8:noTabs=true: