decrypt drsuapi attributes
[wireshark-sm.git] / epan / value_string.c
blobb88e7bdb527cdb94312fabb846890117ed0b6114
1 /* value_string.c
2 * Routines for value_strings
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 #include "config.h"
12 #define WS_LOG_DOMAIN LOG_DOMAIN_EPAN
14 #include <stdio.h>
15 #include <string.h>
17 #include <epan/wmem_scopes.h>
18 #include "proto.h"
19 #include "to_str.h"
20 #include "value_string.h"
21 #include <wsutil/ws_assert.h>
23 #include <wsutil/wslog.h>
25 /* REGULAR VALUE STRING */
27 /* Tries to match val against each element in the value_string array vs.
28 Returns the associated string ptr on a match.
29 Formats val with fmt, and returns the resulting string, on failure. */
30 const char *
31 val_to_str(const uint32_t val, const value_string *vs, const char *fmt)
33 const char *ret;
35 DISSECTOR_ASSERT(fmt != NULL);
37 ret = try_val_to_str(val, vs);
38 if (ret != NULL)
39 return ret;
41 return wmem_strdup_printf(wmem_packet_scope(), fmt, val);
44 char *
45 val_to_str_wmem(wmem_allocator_t *scope, const uint32_t val, const value_string *vs, const char *fmt)
47 const char *ret;
49 DISSECTOR_ASSERT(fmt != NULL);
51 ret = try_val_to_str(val, vs);
52 if (ret != NULL)
53 return wmem_strdup(scope, ret);
55 return wmem_strdup_printf(scope, fmt, val);
58 /* Tries to match val against each element in the value_string array vs.
59 Returns the associated string ptr on a match.
60 Returns 'unknown_str', on failure. */
61 const char *
62 val_to_str_const(const uint32_t val, const value_string *vs,
63 const char *unknown_str)
65 const char *ret;
67 DISSECTOR_ASSERT(unknown_str != NULL);
69 ret = try_val_to_str(val, vs);
70 if (ret != NULL)
71 return ret;
73 return unknown_str;
76 /* Tries to match val against each element in the value_string array vs.
77 Returns the associated string ptr, and sets "*idx" to the index in
78 that table, on a match, and returns NULL, and sets "*idx" to -1,
79 on failure. */
80 const char *
81 try_val_to_str_idx(const uint32_t val, const value_string *vs, int *idx)
83 int i = 0;
85 DISSECTOR_ASSERT(idx != NULL);
87 if(vs) {
88 while (vs[i].strptr) {
89 if (vs[i].value == val) {
90 *idx = i;
91 return(vs[i].strptr);
93 i++;
97 *idx = -1;
98 return NULL;
101 /* Like try_val_to_str_idx(), but doesn't return the index. */
102 const char *
103 try_val_to_str(const uint32_t val, const value_string *vs)
105 int ignore_me;
106 return try_val_to_str_idx(val, vs, &ignore_me);
109 const char *
110 char_val_to_str(char val, const value_string *vs, const char *msg)
112 const char *ret;
113 char buf[7];
115 DISSECTOR_ASSERT(msg != NULL);
117 ret = try_val_to_str(val, vs);
118 if (ret != NULL)
119 return ret;
121 return wmem_strdup_printf(wmem_packet_scope(), "%s: %s",
122 msg, hfinfo_char_value_format_display(BASE_HEX, buf, val));
125 /* 64-BIT VALUE STRING */
127 const char *
128 val64_to_str(const uint64_t val, const val64_string *vs, const char *fmt)
130 const char *ret;
132 DISSECTOR_ASSERT(fmt != NULL);
134 ret = try_val64_to_str(val, vs);
135 if (ret != NULL)
136 return ret;
138 return wmem_strdup_printf(wmem_packet_scope(), fmt, val);
141 const char *
142 val64_to_str_const(const uint64_t val, const val64_string *vs,
143 const char *unknown_str)
145 const char *ret;
147 DISSECTOR_ASSERT(unknown_str != NULL);
149 ret = try_val64_to_str(val, vs);
150 if (ret != NULL)
151 return ret;
153 return unknown_str;
156 const char *
157 try_val64_to_str_idx(const uint64_t val, const val64_string *vs, int *idx)
159 int i = 0;
161 DISSECTOR_ASSERT(idx != NULL);
163 if(vs) {
164 while (vs[i].strptr) {
165 if (vs[i].value == val) {
166 *idx = i;
167 return(vs[i].strptr);
169 i++;
173 *idx = -1;
174 return NULL;
177 const char *
178 try_val64_to_str(const uint64_t val, const val64_string *vs)
180 int ignore_me;
181 return try_val64_to_str_idx(val, vs, &ignore_me);
184 /* REVERSE VALUE STRING */
186 /* We use the same struct as for regular value strings, but we look up strings
187 * and return values instead */
189 /* Like val_to_str except backwards */
190 uint32_t
191 str_to_val(const char *val, const value_string *vs, const uint32_t err_val)
193 int i;
195 i = str_to_val_idx(val, vs);
197 if (i >= 0) {
198 return vs[i].value;
201 return err_val;
204 /* Find the index of a string in a value_string, or -1 when not present */
206 str_to_val_idx(const char *val, const value_string *vs)
208 int i = 0;
210 if(vs) {
212 while (vs[i].strptr) {
214 if (strcmp(vs[i].strptr, val) == 0) {
215 return i;
218 i++;
223 return -1;
226 /* EXTENDED VALUE STRING */
228 /* Extended value strings allow fast(er) value_string array lookups by
229 * using (if possible) direct access or a binary search of the array.
231 * If the values in the value_string array are a contiguous range of values
232 * from min to max, the value will be used as a direct index into the array.
234 * If the values in the array are not contiguous (ie: there are "gaps"),
235 * but are in assending order a binary search will be used.
237 * If direct access or binary search cannot be used, then a linear search
238 * is used and a warning is emitted.
240 * Note that the value_string array used with VALUE_STRING_EXT_INIT
241 * *must* be terminated with {0, NULL}).
243 * Extended value strings are defined at compile time as follows:
244 * static const value_string vs[] = { {value1, "string1"},
245 * {value2, "string2"},
246 * ...,
247 * {0, NULL}};
248 * static value_string_ext vse = VALUE_STRING_EXT_INIT(vs);
250 * Extended value strings can be created at runtime by calling
251 * value_string_ext_new(<ptr to value_string array>,
252 * <total number of entries in the value_string_array>,
253 * <value_string_name>);
254 * Note: The <total number of entries in the value_string_array> should include
255 * the {0, NULL} entry.
258 /* Create a value_string_ext given a ptr to a value_string array and the total
259 * number of entries. Note that the total number of entries should include the
260 * required {0, NULL} terminating entry of the array.
261 * Returns a pointer to an epan-scoped'd and initialized value_string_ext
262 * struct. */
263 value_string_ext *
264 value_string_ext_new(const value_string *vs, unsigned vs_tot_num_entries,
265 const char *vs_name)
267 value_string_ext *vse;
269 DISSECTOR_ASSERT (vs_name != NULL);
270 DISSECTOR_ASSERT (vs_tot_num_entries > 0);
271 /* Null-terminated value-string ? */
272 DISSECTOR_ASSERT (vs[vs_tot_num_entries-1].strptr == NULL);
274 vse = wmem_new(wmem_epan_scope(), value_string_ext);
275 vse->_vs_p = vs;
276 vse->_vs_num_entries = vs_tot_num_entries - 1;
277 /* We set our 'match' function to the init function, which finishes by
278 * setting the match function properly and then calling it. This is a
279 * simple way to do lazy initialization of extended value strings.
280 * The init function also sets up _vs_first_value for us. */
281 vse->_vs_first_value = 0;
282 vse->_vs_match2 = _try_val_to_str_ext_init;
283 vse->_vs_name = vs_name;
285 return vse;
288 void
289 value_string_ext_free(value_string_ext *vse)
291 wmem_free(wmem_epan_scope(), vse);
294 /* Like try_val_to_str for extended value strings */
295 const char *
296 try_val_to_str_ext(const uint32_t val, value_string_ext *vse)
298 if (vse) {
299 const value_string *vs = vse->_vs_match2(val, vse);
301 if (vs) {
302 return vs->strptr;
306 return NULL;
309 /* Like try_val_to_str_idx for extended value strings */
310 const char *
311 try_val_to_str_idx_ext(const uint32_t val, value_string_ext *vse, int *idx)
313 if (vse) {
314 const value_string *vs = vse->_vs_match2(val, vse);
315 if (vs) {
316 *idx = (int) (vs - vse->_vs_p);
317 return vs->strptr;
320 *idx = -1;
321 return NULL;
324 /* Like val_to_str for extended value strings */
325 const char *
326 val_to_str_ext(const uint32_t val, value_string_ext *vse, const char *fmt)
328 const char *ret;
330 DISSECTOR_ASSERT(fmt != NULL);
332 ret = try_val_to_str_ext(val, vse);
333 if (ret != NULL)
334 return ret;
336 return wmem_strdup_printf(wmem_packet_scope(), fmt, val);
339 char *
340 val_to_str_ext_wmem(wmem_allocator_t *scope, const uint32_t val, value_string_ext *vse, const char *fmt)
342 const char *ret;
344 DISSECTOR_ASSERT(fmt != NULL);
346 ret = try_val_to_str_ext(val, vse);
347 if (ret != NULL)
348 return wmem_strdup(scope, ret);
350 return wmem_strdup_printf(scope, fmt, val);
353 /* Like val_to_str_const for extended value strings */
354 const char *
355 val_to_str_ext_const(const uint32_t val, value_string_ext *vse,
356 const char *unknown_str)
358 const char *ret;
360 DISSECTOR_ASSERT(unknown_str != NULL);
362 ret = try_val_to_str_ext(val, vse);
363 if (ret != NULL)
364 return ret;
366 return unknown_str;
369 /* Fallback linear matching algorithm for extended value strings */
370 static const value_string *
371 _try_val_to_str_linear(const uint32_t val, value_string_ext *vse)
373 const value_string *vs_p = vse->_vs_p;
374 unsigned i;
375 for (i=0; i<vse->_vs_num_entries; i++) {
376 if (vs_p[i].value == val)
377 return &(vs_p[i]);
379 return NULL;
382 /* Constant-time matching algorithm for contiguous extended value strings */
383 static const value_string *
384 _try_val_to_str_index(const uint32_t val, value_string_ext *vse)
386 uint32_t i;
388 i = val - vse->_vs_first_value;
389 if (i < vse->_vs_num_entries) {
390 ws_assert (val == vse->_vs_p[i].value);
391 return &(vse->_vs_p[i]);
393 return NULL;
396 /* Value comparator for sorted extended value strings */
397 static int
398 val_to_str_compar(const void *v_needle, const void *v_item)
400 uint32_t needle = *(const uint32_t *)v_needle;
401 uint32_t value = ((const value_string *)v_item)->value;
402 return needle > value ? 1 : (needle < value ? -1 : 0);
405 /* log(n)-time matching for sorted extended value strings */
406 static const value_string *
407 _try_val_to_str_bsearch(const uint32_t val, value_string_ext *vse)
409 return bsearch(&val, vse->_vs_p, vse->_vs_num_entries,
410 sizeof vse->_vs_p[0], val_to_str_compar);
413 /* Initializes an extended value string. Behaves like a match function to
414 * permit lazy initialization of extended value strings.
415 * - Goes through the value_string array to determine the fastest possible
416 * access method.
417 * - Verifies that the value_string contains no NULL string pointers.
418 * - Verifies that the value_string is terminated by {0, NULL}
420 const value_string *
421 _try_val_to_str_ext_init(const uint32_t val, value_string_ext *vse)
423 const value_string *vs_p = vse->_vs_p;
424 const unsigned vs_num_entries = vse->_vs_num_entries;
426 /* The matching algorithm used:
427 * VS_LIN_SEARCH - slow linear search (as in a normal value string)
428 * VS_BIN_SEARCH - log(n)-time binary search, the values must be sorted
429 * VS_INDEX - constant-time index lookup, the values must be contiguous
431 enum { VS_LIN_SEARCH, VS_BIN_SEARCH, VS_INDEX } type = VS_INDEX;
433 /* Note: The value_string 'value' is *unsigned*, but we do a little magic
434 * to help with value strings that have negative values.
436 * { -3, -2, -1, 0, 1, 2 }
437 * will be treated as "ascending ordered" (although it isn't technically),
438 * thus allowing constant-time index search
440 * { -3, -2, 0, 1, 2 } and { -3, -2, -1, 0, 2 }
441 * will both be considered as "out-of-order with gaps", thus falling
442 * back to the slow linear search
444 * { 0, 1, 2, -3, -2 } and { 0, 2, -3, -2, -1 }
445 * will be considered "ascending ordered with gaps" thus allowing
446 * a log(n)-time 'binary' search
448 * If you're confused, think of how negative values are represented, or
449 * google two's complement.
452 uint32_t prev_value;
453 uint32_t first_value;
454 unsigned i;
456 DISSECTOR_ASSERT((vs_p[vs_num_entries].value == 0) &&
457 (vs_p[vs_num_entries].strptr == NULL));
459 vse->_vs_first_value = vs_p[0].value;
460 first_value = vs_p[0].value;
461 prev_value = first_value;
463 for (i = 0; i < vs_num_entries; i++) {
464 DISSECTOR_ASSERT(vs_p[i].strptr != NULL);
465 if ((type == VS_INDEX) && (vs_p[i].value != (i + first_value))) {
466 type = VS_BIN_SEARCH;
468 /* XXX: Should check for dups ?? */
469 if (type == VS_BIN_SEARCH) {
470 if (prev_value > vs_p[i].value) {
471 ws_warning("Extended value string '%s' forced to fall back to linear search:\n"
472 " entry %u, value %u [%#x] < previous entry, value %u [%#x]",
473 vse->_vs_name, i, vs_p[i].value, vs_p[i].value, prev_value, prev_value);
474 type = VS_LIN_SEARCH;
475 break;
477 if (first_value > vs_p[i].value) {
478 ws_warning("Extended value string '%s' forced to fall back to linear search:\n"
479 " entry %u, value %u [%#x] < first entry, value %u [%#x]",
480 vse->_vs_name, i, vs_p[i].value, vs_p[i].value, first_value, first_value);
481 type = VS_LIN_SEARCH;
482 break;
486 prev_value = vs_p[i].value;
489 switch (type) {
490 case VS_LIN_SEARCH:
491 vse->_vs_match2 = _try_val_to_str_linear;
492 break;
493 case VS_BIN_SEARCH:
494 vse->_vs_match2 = _try_val_to_str_bsearch;
495 break;
496 case VS_INDEX:
497 vse->_vs_match2 = _try_val_to_str_index;
498 break;
499 default:
500 ws_assert_not_reached();
501 break;
504 return vse->_vs_match2(val, vse);
507 /* EXTENDED 64-BIT VALUE STRING */
509 /* Extended value strings allow fast(er) val64_string array lookups by
510 * using (if possible) direct access or a binary search of the array.
512 * If the values in the val64_string array are a contiguous range of values
513 * from min to max, the value will be used as a direct index into the array.
515 * If the values in the array are not contiguous (ie: there are "gaps"),
516 * but are in assending order a binary search will be used.
518 * If direct access or binary search cannot be used, then a linear search
519 * is used and a warning is emitted.
521 * Note that the val64_string array used with VAL64_STRING_EXT_INIT
522 * *must* be terminated with {0, NULL}).
524 * Extended value strings are defined at compile time as follows:
525 * static const val64_string vs[] = { {value1, "string1"},
526 * {value2, "string2"},
527 * ...,
528 * {0, NULL}};
529 * static val64_string_ext vse = VAL64_STRING_EXT_INIT(vs);
531 * Extended value strings can be created at runtime by calling
532 * val64_string_ext_new(<ptr to val64_string array>,
533 * <total number of entries in the val64_string_array>,
534 * <val64_string_name>);
535 * Note: The <total number of entries in the val64_string_array> should include
536 * the {0, NULL} entry.
539 /* Create a val64_string_ext given a ptr to a val64_string array and the total
540 * number of entries. Note that the total number of entries should include the
541 * required {0, NULL} terminating entry of the array.
542 * Returns a pointer to an epan-scoped'd and initialized val64_string_ext
543 * struct. */
544 val64_string_ext *
545 val64_string_ext_new(const val64_string *vs, unsigned vs_tot_num_entries,
546 const char *vs_name)
548 val64_string_ext *vse;
550 DISSECTOR_ASSERT (vs_name != NULL);
551 DISSECTOR_ASSERT (vs_tot_num_entries > 0);
552 /* Null-terminated value-string ? */
553 DISSECTOR_ASSERT (vs[vs_tot_num_entries-1].strptr == NULL);
555 vse = wmem_new(wmem_epan_scope(), val64_string_ext);
556 vse->_vs_p = vs;
557 vse->_vs_num_entries = vs_tot_num_entries - 1;
558 /* We set our 'match' function to the init function, which finishes by
559 * setting the match function properly and then calling it. This is a
560 * simple way to do lazy initialization of extended value strings.
561 * The init function also sets up _vs_first_value for us. */
562 vse->_vs_first_value = 0;
563 vse->_vs_match2 = _try_val64_to_str_ext_init;
564 vse->_vs_name = vs_name;
566 return vse;
569 void
570 val64_string_ext_free(val64_string_ext *vse)
572 wmem_free(wmem_epan_scope(), vse);
575 /* Like try_val_to_str for extended value strings */
576 const char *
577 try_val64_to_str_ext(const uint64_t val, val64_string_ext *vse)
579 if (vse) {
580 const val64_string *vs = vse->_vs_match2(val, vse);
582 if (vs) {
583 return vs->strptr;
587 return NULL;
590 /* Like try_val_to_str_idx for extended value strings */
591 const char *
592 try_val64_to_str_idx_ext(const uint64_t val, val64_string_ext *vse, int *idx)
594 if (vse) {
595 const val64_string *vs = vse->_vs_match2(val, vse);
596 if (vs) {
597 *idx = (int) (vs - vse->_vs_p);
598 return vs->strptr;
601 *idx = -1;
602 return NULL;
605 /* Like val_to_str for extended value strings */
606 const char *
607 val64_to_str_ext(const uint64_t val, val64_string_ext *vse, const char *fmt)
609 const char *ret;
611 DISSECTOR_ASSERT(fmt != NULL);
613 ret = try_val64_to_str_ext(val, vse);
614 if (ret != NULL)
615 return ret;
617 return wmem_strdup_printf(wmem_packet_scope(), fmt, val);
620 char *
621 val64_to_str_ext_wmem(wmem_allocator_t *scope, const uint64_t val, val64_string_ext *vse, const char *fmt)
623 const char *ret;
625 DISSECTOR_ASSERT(fmt != NULL);
627 ret = try_val64_to_str_ext(val, vse);
628 if (ret != NULL)
629 return wmem_strdup(scope, ret);
631 return wmem_strdup_printf(scope, fmt, val);
634 /* Like val_to_str_const for extended value strings */
635 const char *
636 val64_to_str_ext_const(const uint64_t val, val64_string_ext *vse,
637 const char *unknown_str)
639 const char *ret;
641 DISSECTOR_ASSERT(unknown_str != NULL);
643 ret = try_val64_to_str_ext(val, vse);
644 if (ret != NULL)
645 return ret;
647 return unknown_str;
650 /* Fallback linear matching algorithm for extended value strings */
651 static const val64_string *
652 _try_val64_to_str_linear(const uint64_t val, val64_string_ext *vse)
654 const val64_string *vs_p = vse->_vs_p;
655 unsigned i;
656 for (i=0; i<vse->_vs_num_entries; i++) {
657 if (vs_p[i].value == val)
658 return &(vs_p[i]);
660 return NULL;
663 /* Constant-time matching algorithm for contiguous extended value strings */
664 static const val64_string *
665 _try_val64_to_str_index(const uint64_t val, val64_string_ext *vse)
667 uint64_t i;
669 i = val - vse->_vs_first_value;
670 if (i < vse->_vs_num_entries) {
671 ws_assert (val == vse->_vs_p[i].value);
672 return &(vse->_vs_p[i]);
674 return NULL;
677 /* Value comparator for sorted extended value strings */
678 static int
679 val64_to_str_compar(const void *v_needle, const void *v_item)
681 uint64_t needle = *(const uint64_t *)v_needle;
682 uint64_t value = ((const val64_string *)v_item)->value;
683 return needle > value ? 1 : (needle < value ? -1 : 0);
686 /* log(n)-time matching for sorted extended value strings */
687 static const val64_string *
688 _try_val64_to_str_bsearch(const uint64_t val, val64_string_ext *vse)
690 return bsearch(&val, vse->_vs_p, vse->_vs_num_entries,
691 sizeof vse->_vs_p[0], val64_to_str_compar);
694 /* Initializes an extended value string. Behaves like a match function to
695 * permit lazy initialization of extended value strings.
696 * - Goes through the val64_string array to determine the fastest possible
697 * access method.
698 * - Verifies that the val64_string contains no NULL string pointers.
699 * - Verifies that the val64_string is terminated by {0, NULL}
701 const val64_string *
702 _try_val64_to_str_ext_init(const uint64_t val, val64_string_ext *vse)
704 const val64_string *vs_p = vse->_vs_p;
705 const unsigned vs_num_entries = vse->_vs_num_entries;
707 /* The matching algorithm used:
708 * VS_LIN_SEARCH - slow linear search (as in a normal value string)
709 * VS_BIN_SEARCH - log(n)-time binary search, the values must be sorted
710 * VS_INDEX - constant-time index lookup, the values must be contiguous
712 enum { VS_LIN_SEARCH, VS_BIN_SEARCH, VS_INDEX } type = VS_INDEX;
714 /* Note: The val64_string 'value' is *unsigned*, but we do a little magic
715 * to help with value strings that have negative values.
717 * { -3, -2, -1, 0, 1, 2 }
718 * will be treated as "ascending ordered" (although it isn't technically),
719 * thus allowing constant-time index search
721 * { -3, -2, 0, 1, 2 } and { -3, -2, -1, 0, 2 }
722 * will both be considered as "out-of-order with gaps", thus falling
723 * back to the slow linear search
725 * { 0, 1, 2, -3, -2 } and { 0, 2, -3, -2, -1 }
726 * will be considered "ascending ordered with gaps" thus allowing
727 * a log(n)-time 'binary' search
729 * If you're confused, think of how negative values are represented, or
730 * google two's complement.
733 uint64_t prev_value;
734 uint64_t first_value;
735 unsigned i;
737 DISSECTOR_ASSERT((vs_p[vs_num_entries].value == 0) &&
738 (vs_p[vs_num_entries].strptr == NULL));
740 vse->_vs_first_value = vs_p[0].value;
741 first_value = vs_p[0].value;
742 prev_value = first_value;
744 for (i = 0; i < vs_num_entries; i++) {
745 DISSECTOR_ASSERT(vs_p[i].strptr != NULL);
746 if ((type == VS_INDEX) && (vs_p[i].value != (i + first_value))) {
747 type = VS_BIN_SEARCH;
749 /* XXX: Should check for dups ?? */
750 if (type == VS_BIN_SEARCH) {
751 if (prev_value > vs_p[i].value) {
752 ws_warning("Extended value string '%s' forced to fall back to linear search:\n"
753 " entry %u, value %" PRIu64 " [%#" PRIx64 "] < previous entry, value %" PRIu64 " [%#" PRIx64 "]",
754 vse->_vs_name, i, vs_p[i].value, vs_p[i].value, prev_value, prev_value);
755 type = VS_LIN_SEARCH;
756 break;
758 if (first_value > vs_p[i].value) {
759 ws_warning("Extended value string '%s' forced to fall back to linear search:\n"
760 " entry %u, value %" PRIu64 " [%#" PRIx64 "] < first entry, value %" PRIu64 " [%#" PRIx64 "]",
761 vse->_vs_name, i, vs_p[i].value, vs_p[i].value, first_value, first_value);
762 type = VS_LIN_SEARCH;
763 break;
767 prev_value = vs_p[i].value;
770 switch (type) {
771 case VS_LIN_SEARCH:
772 vse->_vs_match2 = _try_val64_to_str_linear;
773 break;
774 case VS_BIN_SEARCH:
775 vse->_vs_match2 = _try_val64_to_str_bsearch;
776 break;
777 case VS_INDEX:
778 vse->_vs_match2 = _try_val64_to_str_index;
779 break;
780 default:
781 ws_assert_not_reached();
782 break;
785 return vse->_vs_match2(val, vse);
788 /* STRING TO STRING MATCHING */
790 /* string_string is like value_string except the values being matched are
791 * also strings (instead of unsigned integers) */
793 /* Like val_to_str except for string_string */
794 const char *
795 str_to_str(const char *val, const string_string *vs, const char *fmt)
797 const char *ret;
799 DISSECTOR_ASSERT(fmt != NULL);
801 ret = try_str_to_str(val, vs);
802 if (ret != NULL)
803 return ret;
805 return wmem_strdup_printf(wmem_packet_scope(), fmt, val);
808 /* Like try_val_to_str_idx except for string_string */
809 const char *
810 try_str_to_str_idx(const char *val, const string_string *vs, int *idx)
812 int i = 0;
814 if(vs) {
815 while (vs[i].strptr) {
816 if (!strcmp(vs[i].value,val)) {
817 *idx = i;
818 return(vs[i].strptr);
820 i++;
824 *idx = -1;
825 return NULL;
828 /* Like try_val_to_str except for string_string */
829 const char *
830 try_str_to_str(const char *val, const string_string *vs)
832 int ignore_me;
833 return try_str_to_str_idx(val, vs, &ignore_me);
836 /* RANGE TO STRING MATCHING */
838 /* range_string is like value_string except the values being matched are
839 * integer ranges (for example, 0-10, 11-19, etc.) instead of single values. */
841 /* Like val_to_str except for range_string */
842 const char *
843 rval_to_str(const uint32_t val, const range_string *rs, const char *fmt)
845 const char *ret = NULL;
847 DISSECTOR_ASSERT(fmt != NULL);
849 ret = try_rval_to_str(val, rs);
850 if(ret != NULL)
851 return ret;
853 return wmem_strdup_printf(wmem_packet_scope(), fmt, val);
856 /* Like val_to_str_const except for range_string */
857 const char *
858 rval_to_str_const(const uint32_t val, const range_string *rs,
859 const char *unknown_str)
861 const char *ret = NULL;
863 DISSECTOR_ASSERT(unknown_str != NULL);
865 ret = try_rval_to_str(val, rs);
866 if(ret != NULL)
867 return ret;
869 return unknown_str;
872 /* Like try_val_to_str_idx except for range_string */
873 const char *
874 try_rval_to_str_idx(const uint32_t val, const range_string *rs, int *idx)
876 int i = 0;
878 if(rs) {
879 while(rs[i].strptr) {
880 if( (val >= rs[i].value_min) && (val <= rs[i].value_max) ) {
881 *idx = i;
882 return (rs[i].strptr);
884 i++;
888 *idx = -1;
889 return NULL;
892 /* Like try_val_to_str except for range_string */
893 const char *
894 try_rval_to_str(const uint32_t val, const range_string *rs)
896 int ignore_me = 0;
897 return try_rval_to_str_idx(val, rs, &ignore_me);
900 /* Like try_val_to_str_idx except for range_string */
901 const char *
902 try_rval64_to_str_idx(const uint64_t val, const range_string *rs, int *idx)
904 int i = 0;
906 if(rs) {
907 while(rs[i].strptr) {
908 if( (val >= rs[i].value_min) && (val <= rs[i].value_max) ) {
909 *idx = i;
910 return (rs[i].strptr);
912 i++;
916 *idx = -1;
917 return NULL;
920 /* Like try_val64_to_str except for range_string */
921 const char *
922 try_rval64_to_str(const uint64_t val, const range_string *rs)
924 int ignore_me = 0;
925 return try_rval64_to_str_idx(val, rs, &ignore_me);
929 /* BYTE BUFFER TO STRING MATCHING */
931 /* Like val_to_str except for bytes_string */
932 const char *
933 bytesval_to_str(const uint8_t *val, const size_t val_len, const bytes_string *bs, const char *fmt)
935 const char *ret;
937 DISSECTOR_ASSERT(fmt != NULL);
939 ret = try_bytesval_to_str(val, val_len, bs);
940 if (ret != NULL)
941 return ret;
944 * XXX should this use bytes_to_str as format parameter for consistency?
945 * Though for bytes I guess most of the time you want to show "Unknown"
946 * anyway rather than "Unknown (\x13\x37...)"
948 return wmem_strdup(wmem_packet_scope(), fmt);
951 /* Like try_val_to_str except for bytes_string */
952 const char *
953 try_bytesval_to_str(const uint8_t *val, const size_t val_len, const bytes_string *bs)
955 unsigned i = 0;
957 if (bs) {
958 while (bs[i].strptr) {
959 if (bs[i].value_length == val_len && !memcmp(bs[i].value, val, val_len)) {
960 return bs[i].strptr;
962 i++;
966 return NULL;
969 /* Like val_to_str, but tries to find a prefix (instead of an exact) match
970 of any prefix from the bytes_string array bs against the haystack. */
971 const char *
972 bytesprefix_to_str(const uint8_t *haystack, const size_t haystack_len, const bytes_string *bs, const char *fmt)
974 const char *ret;
976 DISSECTOR_ASSERT(fmt != NULL);
978 ret = try_bytesprefix_to_str(haystack, haystack_len, bs);
979 if (ret != NULL)
980 return ret;
982 /* XXX See note at bytesval_to_str. */
983 return wmem_strdup(wmem_packet_scope(), fmt);
986 /* Like try_val_to_str, but tries to find a prefix (instead of an exact) match
987 of any prefix from the bytes_string array bs against the haystack. */
988 const char *
989 try_bytesprefix_to_str(const uint8_t *haystack, const size_t haystack_len, const bytes_string *bs)
991 unsigned i = 0;
993 if (bs) {
994 while (bs[i].strptr) {
995 if (haystack_len >= bs[i].value_length &&
996 !memcmp(bs[i].value, haystack, bs[i].value_length)) {
997 return bs[i].strptr;
999 i++;
1003 return NULL;
1006 /* MISC */
1008 /* Functions for use by proto_registrar_dump_values(), see proto.c */
1010 bool
1011 value_string_ext_validate(const value_string_ext *vse)
1013 if (vse == NULL)
1014 return false;
1015 #ifndef _WIN32 /* doesn't work on Windows for refs from another DLL ?? */
1016 if ((vse->_vs_match2 != _try_val_to_str_ext_init) &&
1017 (vse->_vs_match2 != _try_val_to_str_linear) &&
1018 (vse->_vs_match2 != _try_val_to_str_bsearch) &&
1019 (vse->_vs_match2 != _try_val_to_str_index))
1020 return false;
1021 #endif
1022 return true;
1025 const char *
1026 value_string_ext_match_type_str(const value_string_ext *vse)
1028 if (vse->_vs_match2 == _try_val_to_str_ext_init)
1029 return "[Not Initialized]";
1030 if (vse->_vs_match2 == _try_val_to_str_linear)
1031 return "[Linear Search]";
1032 if (vse->_vs_match2 == _try_val_to_str_bsearch)
1033 return "[Binary Search]";
1034 if (vse->_vs_match2 == _try_val_to_str_index)
1035 return "[Direct (indexed) Access]";
1036 return "[Invalid]";
1039 bool
1040 val64_string_ext_validate(const val64_string_ext *vse)
1042 if (vse == NULL)
1043 return false;
1044 #ifndef _WIN32 /* doesn't work on Windows for refs from another DLL ?? */
1045 if ((vse->_vs_match2 != _try_val64_to_str_ext_init) &&
1046 (vse->_vs_match2 != _try_val64_to_str_linear) &&
1047 (vse->_vs_match2 != _try_val64_to_str_bsearch) &&
1048 (vse->_vs_match2 != _try_val64_to_str_index))
1049 return false;
1050 #endif
1051 return true;
1054 const char *
1055 val64_string_ext_match_type_str(const val64_string_ext *vse)
1057 if (vse->_vs_match2 == _try_val64_to_str_ext_init)
1058 return "[Not Initialized]";
1059 if (vse->_vs_match2 == _try_val64_to_str_linear)
1060 return "[Linear Search]";
1061 if (vse->_vs_match2 == _try_val64_to_str_bsearch)
1062 return "[Binary Search]";
1063 if (vse->_vs_match2 == _try_val64_to_str_index)
1064 return "[Direct (indexed) Access]";
1065 return "[Invalid]";
1069 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1071 * Local variables:
1072 * c-basic-offset: 4
1073 * tab-width: 8
1074 * indent-tabs-mode: nil
1075 * End:
1077 * vi: set shiftwidth=4 tabstop=8 expandtab:
1078 * :indentSize=4:tabSize=8:noTabs=true: