diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
commit | e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch) | |
tree | 68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/value_string.c | |
parent | Initial commit. (diff) | |
download | wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip |
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/value_string.c')
-rw-r--r-- | epan/value_string.c | 1087 |
1 files changed, 1087 insertions, 0 deletions
diff --git a/epan/value_string.c b/epan/value_string.c new file mode 100644 index 0000000..82eb833 --- /dev/null +++ b/epan/value_string.c @@ -0,0 +1,1087 @@ +/* value_string.c + * Routines for value_strings + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" +#define WS_LOG_DOMAIN LOG_DOMAIN_EPAN + +#include <stdio.h> +#include <string.h> + +#include <epan/wmem_scopes.h> +#include "proto.h" +#include "to_str.h" +#include "value_string.h" +#include <wsutil/ws_assert.h> + +#include <wsutil/wslog.h> + +/* REGULAR VALUE STRING */ + +/* Tries to match val against each element in the value_string array vs. + Returns the associated string ptr on a match. + Formats val with fmt, and returns the resulting string, on failure. */ +const gchar * +val_to_str(const guint32 val, const value_string *vs, const char *fmt) +{ + const gchar *ret; + + DISSECTOR_ASSERT(fmt != NULL); + + ret = try_val_to_str(val, vs); + if (ret != NULL) + return ret; + + return wmem_strdup_printf(wmem_packet_scope(), fmt, val); +} + +gchar * +val_to_str_wmem(wmem_allocator_t *scope, const guint32 val, const value_string *vs, const char *fmt) +{ + const gchar *ret; + + DISSECTOR_ASSERT(fmt != NULL); + + ret = try_val_to_str(val, vs); + if (ret != NULL) + return wmem_strdup(scope, ret); + + return wmem_strdup_printf(scope, fmt, val); +} + +/* Tries to match val against each element in the value_string array vs. + Returns the associated string ptr on a match. + Returns 'unknown_str', on failure. */ +const gchar * +val_to_str_const(const guint32 val, const value_string *vs, + const char *unknown_str) +{ + const gchar *ret; + + DISSECTOR_ASSERT(unknown_str != NULL); + + ret = try_val_to_str(val, vs); + if (ret != NULL) + return ret; + + return unknown_str; +} + +/* Tries to match val against each element in the value_string array vs. + Returns the associated string ptr, and sets "*idx" to the index in + that table, on a match, and returns NULL, and sets "*idx" to -1, + on failure. */ +const gchar * +try_val_to_str_idx(const guint32 val, const value_string *vs, gint *idx) +{ + gint i = 0; + + DISSECTOR_ASSERT(idx != NULL); + + if(vs) { + while (vs[i].strptr) { + if (vs[i].value == val) { + *idx = i; + return(vs[i].strptr); + } + i++; + } + } + + *idx = -1; + return NULL; +} + +/* Like try_val_to_str_idx(), but doesn't return the index. */ +const gchar * +try_val_to_str(const guint32 val, const value_string *vs) +{ + gint ignore_me; + return try_val_to_str_idx(val, vs, &ignore_me); +} + +const gchar * +char_val_to_str(char val, const value_string *vs, const char *msg) +{ + const gchar *ret; + char buf[7]; + + DISSECTOR_ASSERT(msg != NULL); + + ret = try_val_to_str(val, vs); + if (ret != NULL) + return ret; + + return wmem_strdup_printf(wmem_packet_scope(), "%s: %s", + msg, hfinfo_char_value_format_display(BASE_HEX, buf, val)); +} + +/* 64-BIT VALUE STRING */ + +const gchar * +val64_to_str(const guint64 val, const val64_string *vs, const char *fmt) +{ + const gchar *ret; + + DISSECTOR_ASSERT(fmt != NULL); + + ret = try_val64_to_str(val, vs); + if (ret != NULL) + return ret; + + return wmem_strdup_printf(wmem_packet_scope(), fmt, val); +} + +const gchar * +val64_to_str_const(const guint64 val, const val64_string *vs, + const char *unknown_str) +{ + const gchar *ret; + + DISSECTOR_ASSERT(unknown_str != NULL); + + ret = try_val64_to_str(val, vs); + if (ret != NULL) + return ret; + + return unknown_str; +} + +const gchar * +try_val64_to_str_idx(const guint64 val, const val64_string *vs, gint *idx) +{ + gint i = 0; + + DISSECTOR_ASSERT(idx != NULL); + + if(vs) { + while (vs[i].strptr) { + if (vs[i].value == val) { + *idx = i; + return(vs[i].strptr); + } + i++; + } + } + + *idx = -1; + return NULL; +} + +const gchar * +try_val64_to_str(const guint64 val, const val64_string *vs) +{ + gint ignore_me; + return try_val64_to_str_idx(val, vs, &ignore_me); +} + +/* REVERSE VALUE STRING */ + +/* We use the same struct as for regular value strings, but we look up strings + * and return values instead */ + +/* Like val_to_str except backwards */ +guint32 +str_to_val(const gchar *val, const value_string *vs, const guint32 err_val) +{ + gint i; + + i = str_to_val_idx(val, vs); + + if (i >= 0) { + return vs[i].value; + } + + return err_val; +} + +/* Find the index of a string in a value_string, or -1 when not present */ +gint +str_to_val_idx(const gchar *val, const value_string *vs) +{ + gint i = 0; + + if(vs) { + + while (vs[i].strptr) { + + if (strcmp(vs[i].strptr, val) == 0) { + return i; + } + + i++; + } + + } + + return -1; +} + +/* EXTENDED VALUE STRING */ + +/* Extended value strings allow fast(er) value_string array lookups by + * using (if possible) direct access or a binary search of the array. + * + * If the values in the value_string array are a contiguous range of values + * from min to max, the value will be used as a direct index into the array. + * + * If the values in the array are not contiguous (ie: there are "gaps"), + * but are in assending order a binary search will be used. + * + * If direct access or binary search cannot be used, then a linear search + * is used and a warning is emitted. + * + * Note that the value_string array used with VALUE_STRING_EXT_INIT + * *must* be terminated with {0, NULL}). + * + * Extended value strings are defined at compile time as follows: + * static const value_string vs[] = { {value1, "string1"}, + * {value2, "string2"}, + * ..., + * {0, NULL}}; + * static value_string_ext vse = VALUE_STRING_EXT_INIT(vs); + * + * Extended value strings can be created at runtime by calling + * value_string_ext_new(<ptr to value_string array>, + * <total number of entries in the value_string_array>, + * <value_string_name>); + * Note: The <total number of entries in the value_string_array> should include + * the {0, NULL} entry. + */ + +/* Create a value_string_ext given a ptr to a value_string array and the total + * number of entries. Note that the total number of entries should include the + * required {0, NULL} terminating entry of the array. + * Returns a pointer to an epan-scoped'd and initialized value_string_ext + * struct. */ +value_string_ext * +value_string_ext_new(const value_string *vs, guint vs_tot_num_entries, + const gchar *vs_name) +{ + value_string_ext *vse; + + DISSECTOR_ASSERT (vs_name != NULL); + DISSECTOR_ASSERT (vs_tot_num_entries > 0); + /* Null-terminated value-string ? */ + DISSECTOR_ASSERT (vs[vs_tot_num_entries-1].strptr == NULL); + + vse = wmem_new(wmem_epan_scope(), value_string_ext); + vse->_vs_p = vs; + vse->_vs_num_entries = vs_tot_num_entries - 1; + /* We set our 'match' function to the init function, which finishes by + * setting the match function properly and then calling it. This is a + * simple way to do lazy initialization of extended value strings. + * The init function also sets up _vs_first_value for us. */ + vse->_vs_first_value = 0; + vse->_vs_match2 = _try_val_to_str_ext_init; + vse->_vs_name = vs_name; + + return vse; +} + +void +value_string_ext_free(value_string_ext *vse) +{ + wmem_free(wmem_epan_scope(), vse); +} + +/* Like try_val_to_str for extended value strings */ +const gchar * +try_val_to_str_ext(const guint32 val, value_string_ext *vse) +{ + if (vse) { + const value_string *vs = vse->_vs_match2(val, vse); + + if (vs) { + return vs->strptr; + } + } + + return NULL; +} + +/* Like try_val_to_str_idx for extended value strings */ +const gchar * +try_val_to_str_idx_ext(const guint32 val, value_string_ext *vse, gint *idx) +{ + if (vse) { + const value_string *vs = vse->_vs_match2(val, vse); + if (vs) { + *idx = (gint) (vs - vse->_vs_p); + return vs->strptr; + } + } + *idx = -1; + return NULL; +} + +/* Like val_to_str for extended value strings */ +const gchar * +val_to_str_ext(const guint32 val, value_string_ext *vse, const char *fmt) +{ + const gchar *ret; + + DISSECTOR_ASSERT(fmt != NULL); + + ret = try_val_to_str_ext(val, vse); + if (ret != NULL) + return ret; + + return wmem_strdup_printf(wmem_packet_scope(), fmt, val); +} + +gchar * +val_to_str_ext_wmem(wmem_allocator_t *scope, const guint32 val, value_string_ext *vse, const char *fmt) +{ + const gchar *ret; + + DISSECTOR_ASSERT(fmt != NULL); + + ret = try_val_to_str_ext(val, vse); + if (ret != NULL) + return wmem_strdup(scope, ret); + + return wmem_strdup_printf(scope, fmt, val); +} + +/* Like val_to_str_const for extended value strings */ +const gchar * +val_to_str_ext_const(const guint32 val, value_string_ext *vse, + const char *unknown_str) +{ + const gchar *ret; + + DISSECTOR_ASSERT(unknown_str != NULL); + + ret = try_val_to_str_ext(val, vse); + if (ret != NULL) + return ret; + + return unknown_str; +} + +/* Fallback linear matching algorithm for extended value strings */ +static const value_string * +_try_val_to_str_linear(const guint32 val, value_string_ext *vse) +{ + const value_string *vs_p = vse->_vs_p; + guint i; + for (i=0; i<vse->_vs_num_entries; i++) { + if (vs_p[i].value == val) + return &(vs_p[i]); + } + return NULL; +} + +/* Constant-time matching algorithm for contiguous extended value strings */ +static const value_string * +_try_val_to_str_index(const guint32 val, value_string_ext *vse) +{ + guint32 i; + + i = val - vse->_vs_first_value; + if (i < vse->_vs_num_entries) { + ws_assert (val == vse->_vs_p[i].value); + return &(vse->_vs_p[i]); + } + return NULL; +} + +/* log(n)-time matching algorithm for sorted extended value strings */ +static const value_string * +_try_val_to_str_bsearch(const guint32 val, value_string_ext *vse) +{ + guint low, i, max; + guint32 item; + + for (low = 0, max = vse->_vs_num_entries; low < max; ) { + i = (low + max) / 2; + item = vse->_vs_p[i].value; + + if (val < item) + max = i; + else if (val > item) + low = i + 1; + else + return &(vse->_vs_p[i]); + } + return NULL; +} + +/* Initializes an extended value string. Behaves like a match function to + * permit lazy initialization of extended value strings. + * - Goes through the value_string array to determine the fastest possible + * access method. + * - Verifies that the value_string contains no NULL string pointers. + * - Verifies that the value_string is terminated by {0, NULL} + */ +const value_string * +_try_val_to_str_ext_init(const guint32 val, value_string_ext *vse) +{ + const value_string *vs_p = vse->_vs_p; + const guint vs_num_entries = vse->_vs_num_entries; + + /* The matching algorithm used: + * VS_SEARCH - slow sequential search (as in a normal value string) + * VS_BIN_TREE - log(n)-time binary search, the values must be sorted + * VS_INDEX - constant-time index lookup, the values must be contiguous + */ + enum { VS_SEARCH, VS_BIN_TREE, VS_INDEX } type = VS_INDEX; + + /* Note: The value_string 'value' is *unsigned*, but we do a little magic + * to help with value strings that have negative values. + * + * { -3, -2, -1, 0, 1, 2 } + * will be treated as "ascending ordered" (although it isn't technically), + * thus allowing constant-time index search + * + * { -3, -2, 0, 1, 2 } and { -3, -2, -1, 0, 2 } + * will both be considered as "out-of-order with gaps", thus falling + * back to the slow linear search + * + * { 0, 1, 2, -3, -2 } and { 0, 2, -3, -2, -1 } + * will be considered "ascending ordered with gaps" thus allowing + * a log(n)-time 'binary' search + * + * If you're confused, think of how negative values are represented, or + * google two's complement. + */ + + guint32 prev_value; + guint32 first_value; + guint i; + + DISSECTOR_ASSERT((vs_p[vs_num_entries].value == 0) && + (vs_p[vs_num_entries].strptr == NULL)); + + vse->_vs_first_value = vs_p[0].value; + first_value = vs_p[0].value; + prev_value = first_value; + + for (i = 0; i < vs_num_entries; i++) { + DISSECTOR_ASSERT(vs_p[i].strptr != NULL); + if ((type == VS_INDEX) && (vs_p[i].value != (i + first_value))) { + type = VS_BIN_TREE; + } + /* XXX: Should check for dups ?? */ + if (type == VS_BIN_TREE) { + if (prev_value > vs_p[i].value) { + ws_warning("Extended value string '%s' forced to fall back to linear search:\n" + " entry %u, value %u [%#x] < previous entry, value %u [%#x]", + vse->_vs_name, i, vs_p[i].value, vs_p[i].value, prev_value, prev_value); + type = VS_SEARCH; + break; + } + if (first_value > vs_p[i].value) { + ws_warning("Extended value string '%s' forced to fall back to linear search:\n" + " entry %u, value %u [%#x] < first entry, value %u [%#x]", + vse->_vs_name, i, vs_p[i].value, vs_p[i].value, first_value, first_value); + type = VS_SEARCH; + break; + } + } + + prev_value = vs_p[i].value; + } + + switch (type) { + case VS_SEARCH: + vse->_vs_match2 = _try_val_to_str_linear; + break; + case VS_BIN_TREE: + vse->_vs_match2 = _try_val_to_str_bsearch; + break; + case VS_INDEX: + vse->_vs_match2 = _try_val_to_str_index; + break; + default: + ws_assert_not_reached(); + break; + } + + return vse->_vs_match2(val, vse); +} + +/* EXTENDED 64-BIT VALUE STRING */ + +/* Extended value strings allow fast(er) val64_string array lookups by + * using (if possible) direct access or a binary search of the array. + * + * If the values in the val64_string array are a contiguous range of values + * from min to max, the value will be used as a direct index into the array. + * + * If the values in the array are not contiguous (ie: there are "gaps"), + * but are in assending order a binary search will be used. + * + * If direct access or binary search cannot be used, then a linear search + * is used and a warning is emitted. + * + * Note that the val64_string array used with VAL64_STRING_EXT_INIT + * *must* be terminated with {0, NULL}). + * + * Extended value strings are defined at compile time as follows: + * static const val64_string vs[] = { {value1, "string1"}, + * {value2, "string2"}, + * ..., + * {0, NULL}}; + * static val64_string_ext vse = VAL64_STRING_EXT_INIT(vs); + * + * Extended value strings can be created at runtime by calling + * val64_string_ext_new(<ptr to val64_string array>, + * <total number of entries in the val64_string_array>, + * <val64_string_name>); + * Note: The <total number of entries in the val64_string_array> should include + * the {0, NULL} entry. + */ + +/* Create a val64_string_ext given a ptr to a val64_string array and the total + * number of entries. Note that the total number of entries should include the + * required {0, NULL} terminating entry of the array. + * Returns a pointer to an epan-scoped'd and initialized val64_string_ext + * struct. */ +val64_string_ext * +val64_string_ext_new(const val64_string *vs, guint vs_tot_num_entries, + const gchar *vs_name) +{ + val64_string_ext *vse; + + DISSECTOR_ASSERT (vs_name != NULL); + DISSECTOR_ASSERT (vs_tot_num_entries > 0); + /* Null-terminated value-string ? */ + DISSECTOR_ASSERT (vs[vs_tot_num_entries-1].strptr == NULL); + + vse = wmem_new(wmem_epan_scope(), val64_string_ext); + vse->_vs_p = vs; + vse->_vs_num_entries = vs_tot_num_entries - 1; + /* We set our 'match' function to the init function, which finishes by + * setting the match function properly and then calling it. This is a + * simple way to do lazy initialization of extended value strings. + * The init function also sets up _vs_first_value for us. */ + vse->_vs_first_value = 0; + vse->_vs_match2 = _try_val64_to_str_ext_init; + vse->_vs_name = vs_name; + + return vse; +} + +void +val64_string_ext_free(val64_string_ext *vse) +{ + wmem_free(wmem_epan_scope(), vse); +} + +/* Like try_val_to_str for extended value strings */ +const gchar * +try_val64_to_str_ext(const guint64 val, val64_string_ext *vse) +{ + if (vse) { + const val64_string *vs = vse->_vs_match2(val, vse); + + if (vs) { + return vs->strptr; + } + } + + return NULL; +} + +/* Like try_val_to_str_idx for extended value strings */ +const gchar * +try_val64_to_str_idx_ext(const guint64 val, val64_string_ext *vse, gint *idx) +{ + if (vse) { + const val64_string *vs = vse->_vs_match2(val, vse); + if (vs) { + *idx = (gint) (vs - vse->_vs_p); + return vs->strptr; + } + } + *idx = -1; + return NULL; +} + +/* Like val_to_str for extended value strings */ +const gchar * +val64_to_str_ext(const guint64 val, val64_string_ext *vse, const char *fmt) +{ + const gchar *ret; + + DISSECTOR_ASSERT(fmt != NULL); + + ret = try_val64_to_str_ext(val, vse); + if (ret != NULL) + return ret; + + return wmem_strdup_printf(wmem_packet_scope(), fmt, val); +} + +gchar * +val64_to_str_ext_wmem(wmem_allocator_t *scope, const guint64 val, val64_string_ext *vse, const char *fmt) +{ + const gchar *ret; + + DISSECTOR_ASSERT(fmt != NULL); + + ret = try_val64_to_str_ext(val, vse); + if (ret != NULL) + return wmem_strdup(scope, ret); + + return wmem_strdup_printf(scope, fmt, val); +} + +/* Like val_to_str_const for extended value strings */ +const gchar * +val64_to_str_ext_const(const guint64 val, val64_string_ext *vse, + const char *unknown_str) +{ + const gchar *ret; + + DISSECTOR_ASSERT(unknown_str != NULL); + + ret = try_val64_to_str_ext(val, vse); + if (ret != NULL) + return ret; + + return unknown_str; +} + +/* Fallback linear matching algorithm for extended value strings */ +static const val64_string * +_try_val64_to_str_linear(const guint64 val, val64_string_ext *vse) +{ + const val64_string *vs_p = vse->_vs_p; + guint i; + for (i=0; i<vse->_vs_num_entries; i++) { + if (vs_p[i].value == val) + return &(vs_p[i]); + } + return NULL; +} + +/* Constant-time matching algorithm for contiguous extended value strings */ +static const val64_string * +_try_val64_to_str_index(const guint64 val, val64_string_ext *vse) +{ + guint64 i; + + i = val - vse->_vs_first_value; + if (i < vse->_vs_num_entries) { + ws_assert (val == vse->_vs_p[i].value); + return &(vse->_vs_p[i]); + } + return NULL; +} + +/* log(n)-time matching algorithm for sorted extended value strings */ +static const val64_string * +_try_val64_to_str_bsearch(const guint64 val, val64_string_ext *vse) +{ + guint low, i, max; + guint64 item; + + for (low = 0, max = vse->_vs_num_entries; low < max; ) { + i = (low + max) / 2; + item = vse->_vs_p[i].value; + + if (val < item) + max = i; + else if (val > item) + low = i + 1; + else + return &(vse->_vs_p[i]); + } + return NULL; +} + +/* Initializes an extended value string. Behaves like a match function to + * permit lazy initialization of extended value strings. + * - Goes through the val64_string array to determine the fastest possible + * access method. + * - Verifies that the val64_string contains no NULL string pointers. + * - Verifies that the val64_string is terminated by {0, NULL} + */ +const val64_string * +_try_val64_to_str_ext_init(const guint64 val, val64_string_ext *vse) +{ + const val64_string *vs_p = vse->_vs_p; + const guint vs_num_entries = vse->_vs_num_entries; + + /* The matching algorithm used: + * VS_SEARCH - slow sequential search (as in a normal value string) + * VS_BIN_TREE - log(n)-time binary search, the values must be sorted + * VS_INDEX - constant-time index lookup, the values must be contiguous + */ + enum { VS_SEARCH, VS_BIN_TREE, VS_INDEX } type = VS_INDEX; + + /* Note: The val64_string 'value' is *unsigned*, but we do a little magic + * to help with value strings that have negative values. + * + * { -3, -2, -1, 0, 1, 2 } + * will be treated as "ascending ordered" (although it isn't technically), + * thus allowing constant-time index search + * + * { -3, -2, 0, 1, 2 } and { -3, -2, -1, 0, 2 } + * will both be considered as "out-of-order with gaps", thus falling + * back to the slow linear search + * + * { 0, 1, 2, -3, -2 } and { 0, 2, -3, -2, -1 } + * will be considered "ascending ordered with gaps" thus allowing + * a log(n)-time 'binary' search + * + * If you're confused, think of how negative values are represented, or + * google two's complement. + */ + + guint64 prev_value; + guint64 first_value; + guint i; + + DISSECTOR_ASSERT((vs_p[vs_num_entries].value == 0) && + (vs_p[vs_num_entries].strptr == NULL)); + + vse->_vs_first_value = vs_p[0].value; + first_value = vs_p[0].value; + prev_value = first_value; + + for (i = 0; i < vs_num_entries; i++) { + DISSECTOR_ASSERT(vs_p[i].strptr != NULL); + if ((type == VS_INDEX) && (vs_p[i].value != (i + first_value))) { + type = VS_BIN_TREE; + } + /* XXX: Should check for dups ?? */ + if (type == VS_BIN_TREE) { + if (prev_value > vs_p[i].value) { + ws_warning("Extended value string '%s' forced to fall back to linear search:\n" + " entry %u, value %" PRIu64 " [%#" PRIx64 "] < previous entry, value %" PRIu64 " [%#" PRIx64 "]", + vse->_vs_name, i, vs_p[i].value, vs_p[i].value, prev_value, prev_value); + type = VS_SEARCH; + break; + } + if (first_value > vs_p[i].value) { + ws_warning("Extended value string '%s' forced to fall back to linear search:\n" + " entry %u, value %" PRIu64 " [%#" PRIx64 "] < first entry, value %" PRIu64 " [%#" PRIx64 "]", + vse->_vs_name, i, vs_p[i].value, vs_p[i].value, first_value, first_value); + type = VS_SEARCH; + break; + } + } + + prev_value = vs_p[i].value; + } + + switch (type) { + case VS_SEARCH: + vse->_vs_match2 = _try_val64_to_str_linear; + break; + case VS_BIN_TREE: + vse->_vs_match2 = _try_val64_to_str_bsearch; + break; + case VS_INDEX: + vse->_vs_match2 = _try_val64_to_str_index; + break; + default: + ws_assert_not_reached(); + break; + } + + return vse->_vs_match2(val, vse); +} + +/* STRING TO STRING MATCHING */ + +/* string_string is like value_string except the values being matched are + * also strings (instead of unsigned integers) */ + +/* Like val_to_str except for string_string */ +const gchar * +str_to_str(const gchar *val, const string_string *vs, const char *fmt) +{ + const gchar *ret; + + DISSECTOR_ASSERT(fmt != NULL); + + ret = try_str_to_str(val, vs); + if (ret != NULL) + return ret; + + return wmem_strdup_printf(wmem_packet_scope(), fmt, val); +} + +/* Like try_val_to_str_idx except for string_string */ +const gchar * +try_str_to_str_idx(const gchar *val, const string_string *vs, gint *idx) +{ + gint i = 0; + + if(vs) { + while (vs[i].strptr) { + if (!strcmp(vs[i].value,val)) { + *idx = i; + return(vs[i].strptr); + } + i++; + } + } + + *idx = -1; + return NULL; +} + +/* Like try_val_to_str except for string_string */ +const gchar * +try_str_to_str(const gchar *val, const string_string *vs) +{ + gint ignore_me; + return try_str_to_str_idx(val, vs, &ignore_me); +} + +/* RANGE TO STRING MATCHING */ + +/* range_string is like value_string except the values being matched are + * integer ranges (for example, 0-10, 11-19, etc.) instead of single values. */ + +/* Like val_to_str except for range_string */ +const gchar * +rval_to_str(const guint32 val, const range_string *rs, const char *fmt) +{ + const gchar *ret = NULL; + + DISSECTOR_ASSERT(fmt != NULL); + + ret = try_rval_to_str(val, rs); + if(ret != NULL) + return ret; + + return wmem_strdup_printf(wmem_packet_scope(), fmt, val); +} + +/* Like val_to_str_const except for range_string */ +const gchar * +rval_to_str_const(const guint32 val, const range_string *rs, + const char *unknown_str) +{ + const gchar *ret = NULL; + + DISSECTOR_ASSERT(unknown_str != NULL); + + ret = try_rval_to_str(val, rs); + if(ret != NULL) + return ret; + + return unknown_str; +} + +/* Like try_val_to_str_idx except for range_string */ +const gchar * +try_rval_to_str_idx(const guint32 val, const range_string *rs, gint *idx) +{ + gint i = 0; + + if(rs) { + while(rs[i].strptr) { + if( (val >= rs[i].value_min) && (val <= rs[i].value_max) ) { + *idx = i; + return (rs[i].strptr); + } + i++; + } + } + + *idx = -1; + return NULL; +} + +/* Like try_val_to_str except for range_string */ +const gchar * +try_rval_to_str(const guint32 val, const range_string *rs) +{ + gint ignore_me = 0; + return try_rval_to_str_idx(val, rs, &ignore_me); +} + +/* Like try_val_to_str_idx except for range_string */ +const gchar * +try_rval64_to_str_idx(const guint64 val, const range_string *rs, gint *idx) +{ + gint i = 0; + + if(rs) { + while(rs[i].strptr) { + if( (val >= rs[i].value_min) && (val <= rs[i].value_max) ) { + *idx = i; + return (rs[i].strptr); + } + i++; + } + } + + *idx = -1; + return NULL; +} + +/* Like try_val64_to_str except for range_string */ +const gchar * +try_rval64_to_str(const guint64 val, const range_string *rs) +{ + gint ignore_me = 0; + return try_rval64_to_str_idx(val, rs, &ignore_me); +} + + +/* BYTE BUFFER TO STRING MATCHING */ + +/* Like val_to_str except for bytes_string */ +const gchar * +bytesval_to_str(const guint8 *val, const size_t val_len, const bytes_string *bs, const char *fmt) +{ + const gchar *ret; + + DISSECTOR_ASSERT(fmt != NULL); + + ret = try_bytesval_to_str(val, val_len, bs); + if (ret != NULL) + return ret; + + /* + * XXX should this use bytes_to_str as format parameter for consistency? + * Though for bytes I guess most of the time you want to show "Unknown" + * anyway rather than "Unknown (\x13\x37...)" + */ + return wmem_strdup(wmem_packet_scope(), fmt); +} + +/* Like try_val_to_str except for bytes_string */ +const gchar * +try_bytesval_to_str(const guint8 *val, const size_t val_len, const bytes_string *bs) +{ + guint i = 0; + + if (bs) { + while (bs[i].strptr) { + if (bs[i].value_length == val_len && !memcmp(bs[i].value, val, val_len)) { + return bs[i].strptr; + } + i++; + } + } + + return NULL; +} + +/* Like val_to_str, but tries to find a prefix (instead of an exact) match + of any prefix from the bytes_string array bs against the haystack. */ +const gchar * +bytesprefix_to_str(const guint8 *haystack, const size_t haystack_len, const bytes_string *bs, const char *fmt) +{ + const gchar *ret; + + DISSECTOR_ASSERT(fmt != NULL); + + ret = try_bytesprefix_to_str(haystack, haystack_len, bs); + if (ret != NULL) + return ret; + + /* XXX See note at bytesval_to_str. */ + return wmem_strdup(wmem_packet_scope(), fmt); +} + +/* Like try_val_to_str, but tries to find a prefix (instead of an exact) match + of any prefix from the bytes_string array bs against the haystack. */ +const gchar * +try_bytesprefix_to_str(const guint8 *haystack, const size_t haystack_len, const bytes_string *bs) +{ + guint i = 0; + + if (bs) { + while (bs[i].strptr) { + if (haystack_len >= bs[i].value_length && + !memcmp(bs[i].value, haystack, bs[i].value_length)) { + return bs[i].strptr; + } + i++; + } + } + + return NULL; +} + +/* MISC */ + +/* Functions for use by proto_registrar_dump_values(), see proto.c */ + +gboolean +value_string_ext_validate(const value_string_ext *vse) +{ + if (vse == NULL) + return FALSE; +#ifndef _WIN32 /* doesn't work on Windows for refs from another DLL ?? */ + if ((vse->_vs_match2 != _try_val_to_str_ext_init) && + (vse->_vs_match2 != _try_val_to_str_linear) && + (vse->_vs_match2 != _try_val_to_str_bsearch) && + (vse->_vs_match2 != _try_val_to_str_index)) + return FALSE; +#endif + return TRUE; +} + +const gchar * +value_string_ext_match_type_str(const value_string_ext *vse) +{ + if (vse->_vs_match2 == _try_val_to_str_ext_init) + return "[Not Initialized]"; + if (vse->_vs_match2 == _try_val_to_str_linear) + return "[Linear Search]"; + if (vse->_vs_match2 == _try_val_to_str_bsearch) + return "[Binary Search]"; + if (vse->_vs_match2 == _try_val_to_str_index) + return "[Direct (indexed) Access]"; + return "[Invalid]"; +} + +gboolean +val64_string_ext_validate(const val64_string_ext *vse) +{ + if (vse == NULL) + return FALSE; +#ifndef _WIN32 /* doesn't work on Windows for refs from another DLL ?? */ + if ((vse->_vs_match2 != _try_val64_to_str_ext_init) && + (vse->_vs_match2 != _try_val64_to_str_linear) && + (vse->_vs_match2 != _try_val64_to_str_bsearch) && + (vse->_vs_match2 != _try_val64_to_str_index)) + return FALSE; +#endif + return TRUE; +} + +const gchar * +val64_string_ext_match_type_str(const val64_string_ext *vse) +{ + if (vse->_vs_match2 == _try_val64_to_str_ext_init) + return "[Not Initialized]"; + if (vse->_vs_match2 == _try_val64_to_str_linear) + return "[Linear Search]"; + if (vse->_vs_match2 == _try_val64_to_str_bsearch) + return "[Binary Search]"; + if (vse->_vs_match2 == _try_val64_to_str_index) + return "[Direct (indexed) Access]"; + return "[Invalid]"; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ |