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
12 #define WS_LOG_DOMAIN LOG_DOMAIN_EPAN
17 #include <epan/wmem_scopes.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. */
31 val_to_str(const uint32_t val
, const value_string
*vs
, const char *fmt
)
35 DISSECTOR_ASSERT(fmt
!= NULL
);
37 ret
= try_val_to_str(val
, vs
);
41 return wmem_strdup_printf(wmem_packet_scope(), fmt
, val
);
45 val_to_str_wmem(wmem_allocator_t
*scope
, const uint32_t val
, const value_string
*vs
, const char *fmt
)
49 DISSECTOR_ASSERT(fmt
!= NULL
);
51 ret
= try_val_to_str(val
, vs
);
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. */
62 val_to_str_const(const uint32_t val
, const value_string
*vs
,
63 const char *unknown_str
)
67 DISSECTOR_ASSERT(unknown_str
!= NULL
);
69 ret
= try_val_to_str(val
, vs
);
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,
81 try_val_to_str_idx(const uint32_t val
, const value_string
*vs
, int *idx
)
85 DISSECTOR_ASSERT(idx
!= NULL
);
88 while (vs
[i
].strptr
) {
89 if (vs
[i
].value
== val
) {
101 /* Like try_val_to_str_idx(), but doesn't return the index. */
103 try_val_to_str(const uint32_t val
, const value_string
*vs
)
106 return try_val_to_str_idx(val
, vs
, &ignore_me
);
110 char_val_to_str(char val
, const value_string
*vs
, const char *msg
)
115 DISSECTOR_ASSERT(msg
!= NULL
);
117 ret
= try_val_to_str(val
, vs
);
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 */
128 val64_to_str(const uint64_t val
, const val64_string
*vs
, const char *fmt
)
132 DISSECTOR_ASSERT(fmt
!= NULL
);
134 ret
= try_val64_to_str(val
, vs
);
138 return wmem_strdup_printf(wmem_packet_scope(), fmt
, val
);
142 val64_to_str_const(const uint64_t val
, const val64_string
*vs
,
143 const char *unknown_str
)
147 DISSECTOR_ASSERT(unknown_str
!= NULL
);
149 ret
= try_val64_to_str(val
, vs
);
157 try_val64_to_str_idx(const uint64_t val
, const val64_string
*vs
, int *idx
)
161 DISSECTOR_ASSERT(idx
!= NULL
);
164 while (vs
[i
].strptr
) {
165 if (vs
[i
].value
== val
) {
167 return(vs
[i
].strptr
);
178 try_val64_to_str(const uint64_t val
, const val64_string
*vs
)
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 */
191 str_to_val(const char *val
, const value_string
*vs
, const uint32_t err_val
)
195 i
= str_to_val_idx(val
, vs
);
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
)
212 while (vs
[i
].strptr
) {
214 if (strcmp(vs
[i
].strptr
, val
) == 0) {
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"},
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
264 value_string_ext_new(const value_string
*vs
, unsigned vs_tot_num_entries
,
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
);
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
;
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 */
296 try_val_to_str_ext(const uint32_t val
, value_string_ext
*vse
)
299 const value_string
*vs
= vse
->_vs_match2(val
, vse
);
309 /* Like try_val_to_str_idx for extended value strings */
311 try_val_to_str_idx_ext(const uint32_t val
, value_string_ext
*vse
, int *idx
)
314 const value_string
*vs
= vse
->_vs_match2(val
, vse
);
316 *idx
= (int) (vs
- vse
->_vs_p
);
324 /* Like val_to_str for extended value strings */
326 val_to_str_ext(const uint32_t val
, value_string_ext
*vse
, const char *fmt
)
330 DISSECTOR_ASSERT(fmt
!= NULL
);
332 ret
= try_val_to_str_ext(val
, vse
);
336 return wmem_strdup_printf(wmem_packet_scope(), fmt
, val
);
340 val_to_str_ext_wmem(wmem_allocator_t
*scope
, const uint32_t val
, value_string_ext
*vse
, const char *fmt
)
344 DISSECTOR_ASSERT(fmt
!= NULL
);
346 ret
= try_val_to_str_ext(val
, vse
);
348 return wmem_strdup(scope
, ret
);
350 return wmem_strdup_printf(scope
, fmt
, val
);
353 /* Like val_to_str_const for extended value strings */
355 val_to_str_ext_const(const uint32_t val
, value_string_ext
*vse
,
356 const char *unknown_str
)
360 DISSECTOR_ASSERT(unknown_str
!= NULL
);
362 ret
= try_val_to_str_ext(val
, vse
);
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
;
375 for (i
=0; i
<vse
->_vs_num_entries
; i
++) {
376 if (vs_p
[i
].value
== val
)
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
)
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
]);
396 /* Value comparator for sorted extended value strings */
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
417 * - Verifies that the value_string contains no NULL string pointers.
418 * - Verifies that the value_string is terminated by {0, NULL}
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.
453 uint32_t first_value
;
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
;
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
;
486 prev_value
= vs_p
[i
].value
;
491 vse
->_vs_match2
= _try_val_to_str_linear
;
494 vse
->_vs_match2
= _try_val_to_str_bsearch
;
497 vse
->_vs_match2
= _try_val_to_str_index
;
500 ws_assert_not_reached();
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"},
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
545 val64_string_ext_new(const val64_string
*vs
, unsigned vs_tot_num_entries
,
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
);
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
;
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 */
577 try_val64_to_str_ext(const uint64_t val
, val64_string_ext
*vse
)
580 const val64_string
*vs
= vse
->_vs_match2(val
, vse
);
590 /* Like try_val_to_str_idx for extended value strings */
592 try_val64_to_str_idx_ext(const uint64_t val
, val64_string_ext
*vse
, int *idx
)
595 const val64_string
*vs
= vse
->_vs_match2(val
, vse
);
597 *idx
= (int) (vs
- vse
->_vs_p
);
605 /* Like val_to_str for extended value strings */
607 val64_to_str_ext(const uint64_t val
, val64_string_ext
*vse
, const char *fmt
)
611 DISSECTOR_ASSERT(fmt
!= NULL
);
613 ret
= try_val64_to_str_ext(val
, vse
);
617 return wmem_strdup_printf(wmem_packet_scope(), fmt
, val
);
621 val64_to_str_ext_wmem(wmem_allocator_t
*scope
, const uint64_t val
, val64_string_ext
*vse
, const char *fmt
)
625 DISSECTOR_ASSERT(fmt
!= NULL
);
627 ret
= try_val64_to_str_ext(val
, vse
);
629 return wmem_strdup(scope
, ret
);
631 return wmem_strdup_printf(scope
, fmt
, val
);
634 /* Like val_to_str_const for extended value strings */
636 val64_to_str_ext_const(const uint64_t val
, val64_string_ext
*vse
,
637 const char *unknown_str
)
641 DISSECTOR_ASSERT(unknown_str
!= NULL
);
643 ret
= try_val64_to_str_ext(val
, vse
);
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
;
656 for (i
=0; i
<vse
->_vs_num_entries
; i
++) {
657 if (vs_p
[i
].value
== val
)
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
)
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
]);
677 /* Value comparator for sorted extended value strings */
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
698 * - Verifies that the val64_string contains no NULL string pointers.
699 * - Verifies that the val64_string is terminated by {0, NULL}
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.
734 uint64_t first_value
;
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
;
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
;
767 prev_value
= vs_p
[i
].value
;
772 vse
->_vs_match2
= _try_val64_to_str_linear
;
775 vse
->_vs_match2
= _try_val64_to_str_bsearch
;
778 vse
->_vs_match2
= _try_val64_to_str_index
;
781 ws_assert_not_reached();
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 */
795 str_to_str(const char *val
, const string_string
*vs
, const char *fmt
)
799 DISSECTOR_ASSERT(fmt
!= NULL
);
801 ret
= try_str_to_str(val
, vs
);
805 return wmem_strdup_printf(wmem_packet_scope(), fmt
, val
);
808 /* Like try_val_to_str_idx except for string_string */
810 try_str_to_str_idx(const char *val
, const string_string
*vs
, int *idx
)
815 while (vs
[i
].strptr
) {
816 if (!strcmp(vs
[i
].value
,val
)) {
818 return(vs
[i
].strptr
);
828 /* Like try_val_to_str except for string_string */
830 try_str_to_str(const char *val
, const string_string
*vs
)
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 */
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
);
853 return wmem_strdup_printf(wmem_packet_scope(), fmt
, val
);
856 /* Like val_to_str_const except for range_string */
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
);
872 /* Like try_val_to_str_idx except for range_string */
874 try_rval_to_str_idx(const uint32_t val
, const range_string
*rs
, int *idx
)
879 while(rs
[i
].strptr
) {
880 if( (val
>= rs
[i
].value_min
) && (val
<= rs
[i
].value_max
) ) {
882 return (rs
[i
].strptr
);
892 /* Like try_val_to_str except for range_string */
894 try_rval_to_str(const uint32_t val
, const range_string
*rs
)
897 return try_rval_to_str_idx(val
, rs
, &ignore_me
);
900 /* Like try_val_to_str_idx except for range_string */
902 try_rval64_to_str_idx(const uint64_t val
, const range_string
*rs
, int *idx
)
907 while(rs
[i
].strptr
) {
908 if( (val
>= rs
[i
].value_min
) && (val
<= rs
[i
].value_max
) ) {
910 return (rs
[i
].strptr
);
920 /* Like try_val64_to_str except for range_string */
922 try_rval64_to_str(const uint64_t val
, const range_string
*rs
)
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 */
933 bytesval_to_str(const uint8_t *val
, const size_t val_len
, const bytes_string
*bs
, const char *fmt
)
937 DISSECTOR_ASSERT(fmt
!= NULL
);
939 ret
= try_bytesval_to_str(val
, val_len
, bs
);
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 */
953 try_bytesval_to_str(const uint8_t *val
, const size_t val_len
, const bytes_string
*bs
)
958 while (bs
[i
].strptr
) {
959 if (bs
[i
].value_length
== val_len
&& !memcmp(bs
[i
].value
, val
, val_len
)) {
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. */
972 bytesprefix_to_str(const uint8_t *haystack
, const size_t haystack_len
, const bytes_string
*bs
, const char *fmt
)
976 DISSECTOR_ASSERT(fmt
!= NULL
);
978 ret
= try_bytesprefix_to_str(haystack
, haystack_len
, bs
);
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. */
989 try_bytesprefix_to_str(const uint8_t *haystack
, const size_t haystack_len
, const bytes_string
*bs
)
994 while (bs
[i
].strptr
) {
995 if (haystack_len
>= bs
[i
].value_length
&&
996 !memcmp(bs
[i
].value
, haystack
, bs
[i
].value_length
)) {
1008 /* Functions for use by proto_registrar_dump_values(), see proto.c */
1011 value_string_ext_validate(const value_string_ext
*vse
)
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
))
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]";
1040 val64_string_ext_validate(const val64_string_ext
*vse
)
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
))
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]";
1069 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1074 * indent-tabs-mode: nil
1077 * vi: set shiftwidth=4 tabstop=8 expandtab:
1078 * :indentSize=4:tabSize=8:noTabs=true: