2 * Routines for value_strings
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #include "value_string.h"
36 /* --------------------------------------------------------------------*/
37 /* Tries to match val against each element in the value_string array vs.
38 Returns the associated string ptr on a match.
39 Formats val with fmt, and returns the resulting string, on failure. */
41 val_to_str(const guint32 val, const value_string *vs, const char *fmt) {
44 g_assert(fmt != NULL);
46 ret = match_strval(val, vs);
50 return ep_strdup_printf(fmt, val);
53 /* --------------------------------------------------------------------*/
54 /* Tries to match val against each element in the value_string array vs.
55 Returns the associated string ptr on a match.
56 Returns 'unknown_str', on failure. */
58 val_to_str_const(const guint32 val, const value_string *vs, const char *unknown_str) {
61 g_assert(unknown_str != NULL);
63 ret = match_strval(val, vs);
70 /* --------------------------------------------------------------------*/
71 /* Tries to match val against each element in the value_string array vs.
72 Returns the associated string ptr, and sets "*idx" to the index in
73 that table, on a match, and returns NULL, and sets "*idx" to -1,
76 match_strval_idx(const guint32 val, const value_string *vs, gint *idx) {
80 while (vs[i].strptr) {
81 if (vs[i].value == val) {
93 /* Like match_strval_idx(), but doesn't return the index. */
95 match_strval(const guint32 val, const value_string *vs) {
97 return match_strval_idx(val, vs, &ignore_me);
100 /* --------------------------------------------------------------------*/
101 /* value_string_ext functions
103 * Extended value strings allow fast(er) value_string array lookups by
104 * using (if possible) direct access or a binary search of the array.
106 * If the values in the value_string array are a contiguous range of values
107 * from min to max, the value will be used as as a direct index into the array.
109 * If the values in the array are not contiguous (ie: there are "gaps"),
110 * but are in assending order a binary search will be used.
112 * If direct access or binary search cannot be used, then a linear search
115 * Note that the value_string array used with VALUE_STRING_EXT_INIT
116 * *must* be terminated with {0, NULL}).
118 * Extended value strings are defined at compile time as follows:
119 * static const value_string vs[] = { {value1, "string1"}, {value2, "string2"}, ..., {0, NULL}};
120 * static value_string_ext vse = VALUE_STRING_EXT_INIT(vs);
122 * Extended value strings can be created at runtime by calling
123 * value_string_ext_new(<ptr to value_string array>,
124 * <total number of entries in the value_string_array>,
125 * <value_string_name>);
126 * Note: <total number of entries in the value_string_array> should include the {0, NULL} entry
130 /* --------------------------------------------------------------------*/
132 /* Create a value_string_ext given a ptr to a value_string array and the total number of entries. */
133 /* Note: The total number of entries should include the required {0, NULL} terminating entry of the array. */
134 /* Return: a pointer to a gmalloc'd and initialized value_string_ext struct. */
136 value_string_ext_new(value_string *vs, guint vs_tot_num_entries, gchar *vs_name) {
137 value_string_ext *vse;
138 g_assert (vs_name != NULL);
139 g_assert (vs_tot_num_entries > 0);
140 g_assert (vs[vs_tot_num_entries-1].strptr == NULL); /* Null-terminated value-string ? */
141 vse = g_malloc(sizeof (value_string_ext));
143 vse->_vs_num_entries = vs_tot_num_entries - 1; /* remember the actual number of entries */
144 vse->_vs_first_value = 0; /* initialized in _match_strval_ext_init */
145 vse->_vs_match = (_value_string_match_t) _match_strval_ext_init;
146 vse->_vs_name = vs_name;
150 /* Looks up val in a value_string array using access method (direct, binary search
151 * or linear) determined at rutime during the initial access); (see _match_strval_ext_init)
152 * Returns the associated string ptr on a match, and returns NULL on failure.
155 match_strval_ext(const guint32 val, const value_string_ext *vse) {
157 return vse->_vs_match(val, vse);
161 /* Similar to match_strval_ext except that on failure
162 * Formats val with fmt, and returns the resulting string
165 val_to_str_ext(const guint32 val, const value_string_ext *vse, const char *fmt) {
168 g_assert(fmt != NULL);
170 ret = match_strval_ext(val, vse);
174 return ep_strdup_printf(fmt, val);
177 /* Similar to match_strval_ext except that on failure
178 * Returns 'unknown_str'
181 val_to_str_ext_const(const guint32 val, const value_string_ext *vse, const char *unknown_str) {
184 g_assert(unknown_str != NULL);
186 ret = match_strval_ext(val, vse);
194 _match_strval_linear(const guint32 val, const value_string_ext *vse)
196 const value_string *vs_p = vse->_vs_p;
198 for (i=0; i<vse->_vs_num_entries; i++) {
199 if (vs_p[i].value == val) {
200 return vs_p[i].strptr;
207 _match_strval_index(const guint32 val, const value_string_ext *vse)
209 if ((val - vse->_vs_first_value) < vse->_vs_num_entries) {
210 g_assert (val == vse->_vs_p[val - vse->_vs_first_value].value);
211 return vse->_vs_p[val - vse->_vs_first_value].strptr;
217 _match_strval_bsearch(const guint32 val, const value_string_ext *vse)
222 for (low = 0, max = vse->_vs_num_entries; low < max; ) {
223 idx = (low + max) / 2;
224 item = vse->_vs_p[idx].value;
231 return vse->_vs_p[idx].strptr;
236 /* Init value_string_ext struct
237 - Go thru the value_string array to determine whether indexed access
238 or binary search access is possible;
239 - Verify that the value_string array does not contain any
240 NULL string pointers;
241 - Verify that the value_string array is terminated
245 _match_strval_ext_init(const guint32 val, value_string_ext *vse)
247 const value_string *vs_p = vse->_vs_p;
248 const guint vs_num_entries = vse->_vs_num_entries;
250 /* The way matching of value is done in a value_string:
251 * 0 Sequential search (as in a normal value string)
252 * 1 Binary search, the values MUST be in numerical order.
253 * 2 The value used as an index(the value string MUST have all values between first and last defined in numerical order)
255 enum { VS_SEARCH = 0, VS_BIN_TREE, VS_INDEX } type = VS_INDEX;
261 g_assert((vs_p[vs_num_entries].value==0) && (vs_p[vs_num_entries].strptr==NULL));
263 vse->_vs_first_value = vs_p[0].value;
264 first_value = vs_p[0].value;
265 prev_value = first_value;
267 for (i = 0; i < vs_num_entries; i++) {
268 g_assert(vs_p[i].strptr != NULL);
269 if ((type == VS_INDEX) && (vs_p[i].value != (i + first_value))) {
272 /* XXX: Should check for dups ?? */
273 if ((type == VS_BIN_TREE) && (prev_value > vs_p[i].value)) {
278 prev_value = vs_p[i].value;
283 vse->_vs_match = _match_strval_linear;
284 g_warning("Extended value string: %s not sorted; accessing linearly (%0x/%0x)",
285 vse->_vs_name, prev_value, vs_p[i].value);
288 vse->_vs_match = _match_strval_bsearch;
291 vse->_vs_match = _match_strval_index;
294 g_assert_not_reached();
298 return vse->_vs_match(val, vse);
302 /* Tries to match val against each element in the value_string array vs.
303 Returns the associated string ptr on a match.
304 Formats val with fmt, and returns the resulting string, on failure. */
306 str_to_str(const gchar *val, const string_string *vs, const char *fmt) {
309 g_assert(fmt != NULL);
311 ret = match_strstr(val, vs);
315 return ep_strdup_printf(fmt, val);
318 /* Tries to match val against each element in the value_string array vs.
319 Returns the associated string ptr, and sets "*idx" to the index in
320 that table, on a match, and returns NULL, and sets "*idx" to -1,
323 match_strstr_idx(const gchar *val, const string_string *vs, gint *idx) {
327 while (vs[i].strptr) {
328 if (!strcmp(vs[i].value,val)) {
330 return(vs[i].strptr);
340 /* Like match_strval_idx(), but doesn't return the index. */
342 match_strstr(const gchar *val, const string_string *vs) {
344 return match_strstr_idx(val, vs, &ignore_me);
347 /* Generate a string describing an enumerated bitfield (an N-bit field
348 with various specific values having particular names). */
350 decode_enumerated_bitfield(const guint32 val, const guint32 mask, const int width,
351 const value_string *tab, const char *fmt)
353 static char buf[1025];
356 p = decode_bitfield_value(buf, val, mask, width);
357 g_snprintf(p, (gulong) (1024-(p-buf)), fmt, val_to_str(val & mask, tab, "Unknown"));
362 /* Generate a string describing an enumerated bitfield (an N-bit field
363 with various specific values having particular names). */
365 decode_enumerated_bitfield_shifted(const guint32 val, const guint32 mask, const int width,
366 const value_string *tab, const char *fmt)
368 static char buf[1025];
372 /* Compute the number of bits we have to shift the bitfield right
373 to extract its value. */
374 while ((mask & (1<<shift)) == 0)
377 p = decode_bitfield_value(buf, val, mask, width);
378 g_snprintf(p, (gulong) (1024-(p-buf)), fmt, val_to_str((val & mask) >> shift, tab, "Unknown"));
383 /* FF: ranges aware versions */
385 /* Tries to match val against each range in the range_string array rs.
386 Returns the associated string ptr on a match.
387 Formats val with fmt, and returns the resulting string, on failure. */
388 const gchar *rval_to_str(const guint32 val, const range_string *rs, const char *fmt)
390 const gchar *ret = NULL;
392 g_assert(fmt != NULL);
394 ret = match_strrval(val, rs);
398 return ep_strdup_printf(fmt, val);
401 /* Tries to match val against each range in the range_string array rs.
402 Returns the associated string ptr, and sets "*idx" to the index in
403 that table, on a match, and returns NULL, and sets "*idx" to -1,
405 const gchar *match_strrval_idx(const guint32 val, const range_string *rs, gint *idx)
410 while(rs[i].strptr) {
411 if( (val >= rs[i].value_min) && (val <= rs[i].value_max) ) {
413 return (rs[i].strptr);
423 /* Like match_strrval_idx(), but doesn't return the index. */
424 const gchar *match_strrval(const guint32 val, const range_string *rs)
427 return match_strrval_idx(val, rs, &ignore_me);