forked from osmocom/wireshark
Add support for adding unit names to hf_ fields.
This was inspired by the https://www.wireshark.org/lists/wireshark-dev/201505/msg00029.html thread. Used TCP and NTP dissectors as the guinea pig with sample use. Documentation updates includes some unrelated cleanup just because it was noticed. Change-Id: I59b26e1ca3b95e3473e4757f1759d7ad82976965 Reviewed-on: https://code.wireshark.org/review/19211 Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com> Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
parent
97b41a494c
commit
4e97f74f11
|
@ -1639,6 +1639,16 @@ libwireshark.so.0 libwireshark0 #MINVER#
|
|||
udp_port_to_display@Base 1.99.2
|
||||
uint_to_str_back@Base 2.1.0
|
||||
union_of_tap_listener_flags@Base 1.9.1
|
||||
unit_name_string_get_value@Base 2.3.0
|
||||
unit_name_string_get_value64@Base 2.3.0
|
||||
units_bit_bits@Base 2.3.0
|
||||
units_byte_bytes@Base 2.3.0
|
||||
units_foot_feet@Base 2.3.0
|
||||
units_millisecond_milliseconds@Base 2.3.0
|
||||
units_milliseconds@Base 2.3.0
|
||||
units_second_seconds@Base 2.3.0
|
||||
units_seconds@Base 2.3.0
|
||||
units_word_words@Base 2.3.0
|
||||
unsigned_time_secs_to_str@Base 2.1.0
|
||||
update_crc10_by_bytes_tvb@Base 1.99.0
|
||||
uri_str_to_bytes@Base 1.9.1
|
||||
|
|
|
@ -116,7 +116,8 @@ FIELDDISPLAY --For FT_UINT{8,16,24,32,40,48,56,64} and
|
|||
|
||||
BASE_DEC, BASE_HEX, BASE_OCT, BASE_DEC_HEX, BASE_HEX_DEC,
|
||||
BASE_CUSTOM, or BASE_NONE, possibly ORed with
|
||||
BASE_RANGE_STRING, BASE_EXT_STRING or BASE_VAL64_STRING.
|
||||
BASE_RANGE_STRING, BASE_EXT_STRING, BASE_VAL64_STRING,
|
||||
BASE_ALLOW_ZERO or BASE_UNIT_STRING
|
||||
|
||||
BASE_NONE may be used with a non-NULL FIELDCONVERT when the
|
||||
numeric value of the field itself is not of significance to
|
||||
|
@ -988,6 +989,34 @@ used is a guint64 (instead of guint32). Instead of using the VALS()
|
|||
macro for the 'strings' field in the header_field_info struct array,
|
||||
'VALS64()' is used.
|
||||
|
||||
-- Unit string
|
||||
Some integer fields, of type FT_UINT* and float fiels, of type FT_FLOAT
|
||||
or FT_DOUBLE, need units of measurement to help convey the field value.
|
||||
|
||||
A 'unit_name_string' structure is a way to add a unit suffix to a field.
|
||||
|
||||
typedef struct unit_name_string {
|
||||
char *singular; /* name to use for 1 unit */
|
||||
char *plural; /* name to use for < 1 or > 1 units */
|
||||
} unit_name_string;
|
||||
|
||||
For fields with that unit name, you would declare a "unit_name_string":
|
||||
|
||||
static const unit_name_string unitname[] =
|
||||
{ "single item name" , "multiple item name" };
|
||||
|
||||
(the second entry can be NULL if there is no plural form of the unit name.
|
||||
This is typically the case when abbreviations are used instead of full words.)
|
||||
|
||||
There are several "common" unit name structures already defined in
|
||||
epan/unit_strings.h. Dissector authors may choose to add the unit name
|
||||
structure there rather than locally in a dissector.
|
||||
|
||||
For hf[] array FT_(U)INT*, FT_FlOAT and FT_DOUBLE fields that need a
|
||||
'unit_name_string' struct, the 'strings' field would be set to
|
||||
'&units_second_seconds'. Furthermore, the 'display' field must be ORed
|
||||
with 'BASE_UNIT_STRING' (e.g. BASE_DEC|BASE_UNIT_STRING).
|
||||
|
||||
-- Ranges
|
||||
If the field has a numeric type that might logically fit in ranges of values
|
||||
one can use a range_string struct.
|
||||
|
@ -1826,6 +1855,9 @@ arguments are a "printf"-style format and any arguments for that format.
|
|||
With these routines, unlike the proto_tree_add_XXX_format() routines,
|
||||
the name of the field is added automatically as in the
|
||||
proto_tree_add_XXX() functions; only the value is added with the format.
|
||||
One use case for this would be to add a unit of measurement string to
|
||||
the value of the field, however using BASE_UNIT_STRING in the hf_
|
||||
definition is now preferred.
|
||||
|
||||
proto_tree_add_checksum()
|
||||
----------------------------
|
||||
|
|
|
@ -40,6 +40,9 @@ since version 2.2.0:
|
|||
* TShark can now export objects like the other GUI interfaces.
|
||||
* Support for G.722 and G.726 codecs in the RTP Player (via the SpanDSP library).
|
||||
* You can now choose the output device when playing RTP streams.
|
||||
* Added support for dissectors to include a unit name natively in their hf field.
|
||||
A field can now automatically append "seconds" or "ms" to its value without
|
||||
additional printf-style APIs.
|
||||
|
||||
//=== Removed Dissectors
|
||||
|
||||
|
|
|
@ -167,6 +167,7 @@ set(LIBWIRESHARK_FILES
|
|||
tvbuff_zlib.c
|
||||
uat.c
|
||||
value_string.c
|
||||
unit_strings.c
|
||||
xdlc.c
|
||||
${CMAKE_SOURCE_DIR}/ws_version_info.c
|
||||
)
|
||||
|
|
|
@ -128,6 +128,7 @@ LIBWIRESHARK_SRC = \
|
|||
tvbuff_zlib.c \
|
||||
tvbuff.c \
|
||||
uat.c \
|
||||
unit_strings.c \
|
||||
value_string.c \
|
||||
xdlc.c
|
||||
|
||||
|
@ -290,6 +291,7 @@ LIBWIRESHARK_INCLUDES = \
|
|||
tvbuff-int.h \
|
||||
uat.h \
|
||||
uat-int.h \
|
||||
unit_strings.h \
|
||||
value_string.h \
|
||||
x264_prt_id.h \
|
||||
xdlc.h
|
||||
|
|
|
@ -955,10 +955,7 @@ dissect_ntp_std(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ntp_tree)
|
|||
*/
|
||||
rootdelay = ((gint16)tvb_get_ntohs(tvb, 4)) +
|
||||
(tvb_get_ntohs(tvb, 6) / 65536.0);
|
||||
proto_tree_add_double_format_value(ntp_tree, hf_ntp_rootdelay, tvb, 4, 4,
|
||||
rootdelay,
|
||||
"%9.4f sec",
|
||||
rootdelay);
|
||||
proto_tree_add_double(ntp_tree, hf_ntp_rootdelay, tvb, 4, 4, rootdelay);
|
||||
|
||||
/* Root Dispersion, 32-bit unsigned fixed-point number indicating
|
||||
* the nominal error relative to the primary reference source, in
|
||||
|
@ -966,10 +963,7 @@ dissect_ntp_std(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ntp_tree)
|
|||
*/
|
||||
rootdispersion = ((gint16)tvb_get_ntohs(tvb, 8)) +
|
||||
(tvb_get_ntohs(tvb, 10) / 65536.0);
|
||||
proto_tree_add_double_format_value(ntp_tree, hf_ntp_rootdispersion, tvb, 8, 4,
|
||||
rootdispersion,
|
||||
"%9.4f sec",
|
||||
rootdispersion);
|
||||
proto_tree_add_double(ntp_tree, hf_ntp_rootdispersion, tvb, 8, 4, rootdispersion);
|
||||
|
||||
/* Now, there is a problem with secondary servers. Standards
|
||||
* asks from stratum-2 - stratum-15 servers to set this to the
|
||||
|
@ -1428,11 +1422,11 @@ proto_register_ntp(void)
|
|||
"Peer Clock Precision", "ntp.precision", FT_INT8, BASE_DEC,
|
||||
NULL, 0, "The precision of the system clock", HFILL }},
|
||||
{ &hf_ntp_rootdelay, {
|
||||
"Root Delay", "ntp.rootdelay", FT_DOUBLE, BASE_NONE,
|
||||
NULL, 0, "Total round-trip delay to the reference clock", HFILL }},
|
||||
"Root Delay", "ntp.rootdelay", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING,
|
||||
&units_second_seconds, 0, "Total round-trip delay to the reference clock", HFILL }},
|
||||
{ &hf_ntp_rootdispersion, {
|
||||
"Root Dispersion", "ntp.rootdispersion", FT_DOUBLE, BASE_NONE,
|
||||
NULL, 0, "Total dispersion to the reference clock", HFILL }},
|
||||
"Root Dispersion", "ntp.rootdispersion", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING,
|
||||
&units_second_seconds, 0, "Total dispersion to the reference clock", HFILL }},
|
||||
{ &hf_ntp_refid, {
|
||||
"Reference ID", "ntp.refid", FT_BYTES, BASE_NONE,
|
||||
NULL, 0, "Particular server or reference clock being used", HFILL }},
|
||||
|
|
|
@ -5982,8 +5982,7 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
|||
}
|
||||
|
||||
if (tree) {
|
||||
proto_tree_add_uint_format_value(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen,
|
||||
"%u bytes", tcph->th_hlen);
|
||||
proto_tree_add_uint(tcp_tree, hf_tcp_hdr_len, tvb, offset + 12, 1, tcph->th_hlen);
|
||||
tf = proto_tree_add_uint_format(tcp_tree, hf_tcp_flags, tvb, offset + 12, 2,
|
||||
tcph->th_flags, "Flags: 0x%03x (%s)", tcph->th_flags, flags_str);
|
||||
field_tree = proto_item_add_subtree(tf, ett_tcp_flags);
|
||||
|
@ -6490,7 +6489,7 @@ proto_register_tcp(void)
|
|||
NULL, HFILL }},
|
||||
|
||||
{ &hf_tcp_hdr_len,
|
||||
{ "Header Length", "tcp.hdr_len", FT_UINT8, BASE_DEC, NULL, 0x0,
|
||||
{ "Header Length", "tcp.hdr_len", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &units_byte_bytes, 0x0,
|
||||
NULL, HFILL }},
|
||||
|
||||
{ &hf_tcp_flags,
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "column-utils.h"
|
||||
#include "guid-utils.h"
|
||||
#include "tfs.h"
|
||||
#include "unit_strings.h"
|
||||
#include "ws_symbol_export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
239
epan/proto.c
239
epan/proto.c
|
@ -5114,13 +5114,20 @@ proto_custom_set(proto_tree* tree, GSList *field_ids, gint occurrence,
|
|||
offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
|
||||
|
||||
} else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
|
||||
number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
|
||||
if (hfinfo->display & BASE_UNIT_STRING) {
|
||||
number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
|
||||
offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
|
||||
hf_str_val = hf_try_val_to_str(number, hfinfo);
|
||||
offset_r += protoo_strlcpy(result+offset_r, hf_str_val, size-offset_r);
|
||||
}
|
||||
else {
|
||||
number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
|
||||
|
||||
if (!number_out)
|
||||
number_out = hfinfo_number_value_format_display(hfinfo, BASE_DEC, number_buf, number);
|
||||
|
||||
offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
|
||||
if (!number_out)
|
||||
number_out = hfinfo_number_value_format_display(hfinfo, BASE_DEC, number_buf, number);
|
||||
|
||||
offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
|
||||
}
|
||||
} else {
|
||||
number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
|
||||
|
||||
|
@ -5253,14 +5260,28 @@ proto_custom_set(proto_tree* tree, GSList *field_ids, gint occurrence,
|
|||
break;
|
||||
|
||||
case FT_FLOAT:
|
||||
g_snprintf(result+offset_r, size-offset_r,
|
||||
"%." G_STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
|
||||
if (hfinfo->display & BASE_UNIT_STRING) {
|
||||
double d_value = fvalue_get_floating(&finfo->value);
|
||||
g_snprintf(result+offset_r, size-offset_r,
|
||||
"%." G_STRINGIFY(FLT_DIG) "g%s", d_value,
|
||||
unit_name_string_get_value64((guint64)d_value, (unit_name_string*)hfinfo->strings));
|
||||
} else {
|
||||
g_snprintf(result+offset_r, size-offset_r,
|
||||
"%." G_STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
|
||||
}
|
||||
offset_r = (int)strlen(result);
|
||||
break;
|
||||
|
||||
case FT_DOUBLE:
|
||||
g_snprintf(result+offset_r, size-offset_r,
|
||||
"%." G_STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
|
||||
if (hfinfo->display & BASE_UNIT_STRING) {
|
||||
double d_value = fvalue_get_floating(&finfo->value);
|
||||
g_snprintf(result+offset_r, size-offset_r,
|
||||
"%." G_STRINGIFY(DBL_DIG) "g%s", d_value,
|
||||
unit_name_string_get_value64((guint64)d_value, (unit_name_string*)hfinfo->strings));
|
||||
} else {
|
||||
g_snprintf(result+offset_r, size-offset_r,
|
||||
"%." G_STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
|
||||
}
|
||||
offset_r = (int)strlen(result);
|
||||
break;
|
||||
|
||||
|
@ -6357,19 +6378,31 @@ free_deregistered_field (gpointer data, gpointer user_data _U_)
|
|||
}
|
||||
case FT_UINT64:
|
||||
case FT_INT64: {
|
||||
val64_string *vs64 = (val64_string *)hfi->strings;
|
||||
while (vs64->strptr) {
|
||||
g_free((gchar *)vs64->strptr);
|
||||
vs64++;
|
||||
if (hfi->display & BASE_UNIT_STRING) {
|
||||
unit_name_string *unit = (unit_name_string*)hfi->strings;
|
||||
g_free ((gchar *)unit->singular);
|
||||
g_free ((gchar *)unit->plural);
|
||||
} else {
|
||||
val64_string *vs64 = (val64_string *)hfi->strings;
|
||||
while (vs64->strptr) {
|
||||
g_free((gchar *)vs64->strptr);
|
||||
vs64++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
/* Other Integer types */
|
||||
value_string *vs = (value_string *)hfi->strings;
|
||||
while (vs->strptr) {
|
||||
g_free((gchar *)vs->strptr);
|
||||
vs++;
|
||||
if (hfi->display & BASE_UNIT_STRING) {
|
||||
unit_name_string *unit = (unit_name_string*)hfi->strings;
|
||||
g_free ((gchar *)unit->singular);
|
||||
g_free ((gchar *)unit->plural);
|
||||
} else {
|
||||
value_string *vs = (value_string *)hfi->strings;
|
||||
while (vs->strptr) {
|
||||
g_free((gchar *)vs->strptr);
|
||||
vs++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -6508,30 +6541,42 @@ tmp_fld_check_assert(header_field_info *hfinfo)
|
|||
/* These types of fields are allowed to have value_strings,
|
||||
* true_false_strings or a protocol_t struct
|
||||
*/
|
||||
if (hfinfo->strings != NULL && !(
|
||||
(hfinfo->type == FT_CHAR) ||
|
||||
(hfinfo->type == FT_UINT8) ||
|
||||
(hfinfo->type == FT_UINT16) ||
|
||||
(hfinfo->type == FT_UINT24) ||
|
||||
(hfinfo->type == FT_UINT32) ||
|
||||
(hfinfo->type == FT_UINT40) ||
|
||||
(hfinfo->type == FT_UINT48) ||
|
||||
(hfinfo->type == FT_UINT56) ||
|
||||
(hfinfo->type == FT_UINT64) ||
|
||||
(hfinfo->type == FT_INT8) ||
|
||||
(hfinfo->type == FT_INT16) ||
|
||||
(hfinfo->type == FT_INT24) ||
|
||||
(hfinfo->type == FT_INT32) ||
|
||||
(hfinfo->type == FT_INT40) ||
|
||||
(hfinfo->type == FT_INT48) ||
|
||||
(hfinfo->type == FT_INT56) ||
|
||||
(hfinfo->type == FT_INT64) ||
|
||||
(hfinfo->type == FT_BOOLEAN) ||
|
||||
(hfinfo->type == FT_PROTOCOL) ||
|
||||
(hfinfo->type == FT_FRAMENUM) ))
|
||||
g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
|
||||
" (which is not allowed to have strings)\n",
|
||||
hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type));
|
||||
if (hfinfo->strings != NULL) {
|
||||
switch(hfinfo->type) {
|
||||
case FT_CHAR:
|
||||
case FT_UINT8:
|
||||
case FT_UINT16:
|
||||
case FT_UINT24:
|
||||
case FT_UINT32:
|
||||
case FT_UINT40:
|
||||
case FT_UINT48:
|
||||
case FT_UINT56:
|
||||
case FT_UINT64:
|
||||
case FT_INT8:
|
||||
case FT_INT16:
|
||||
case FT_INT24:
|
||||
case FT_INT32:
|
||||
case FT_INT40:
|
||||
case FT_INT48:
|
||||
case FT_INT56:
|
||||
case FT_INT64:
|
||||
case FT_BOOLEAN:
|
||||
case FT_PROTOCOL:
|
||||
case FT_FRAMENUM:
|
||||
break;
|
||||
case FT_FLOAT:
|
||||
case FT_DOUBLE:
|
||||
//allowed to support string if its a unit decsription
|
||||
if (hfinfo->display & BASE_UNIT_STRING)
|
||||
break;
|
||||
|
||||
//fallthrough
|
||||
default:
|
||||
g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
|
||||
" (which is not allowed to have strings)\n",
|
||||
hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type));
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: This check may slow down startup, and output quite a few warnings.
|
||||
It would be good to be able to enable this (and possibly other checks?)
|
||||
|
@ -6600,7 +6645,7 @@ tmp_fld_check_assert(header_field_info *hfinfo)
|
|||
* meaningless; we'll avoid showing the value to the
|
||||
* user.
|
||||
*/
|
||||
switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
|
||||
switch (FIELD_DISPLAY(hfinfo->display)) {
|
||||
case BASE_HEX:
|
||||
case BASE_OCT:
|
||||
case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
|
||||
|
@ -6621,6 +6666,11 @@ tmp_fld_check_assert(header_field_info *hfinfo)
|
|||
ftype_name(hfinfo->type), tmp_str);
|
||||
wmem_free(NULL, tmp_str);
|
||||
}
|
||||
if (hfinfo->display & BASE_UNIT_STRING) {
|
||||
g_error("Field '%s' (%s) is a character value (%s) but has a unit string\n",
|
||||
hfinfo->name, hfinfo->abbrev,
|
||||
ftype_name(hfinfo->type));
|
||||
}
|
||||
break;
|
||||
case FT_INT8:
|
||||
case FT_INT16:
|
||||
|
@ -6695,13 +6745,15 @@ tmp_fld_check_assert(header_field_info *hfinfo)
|
|||
case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
|
||||
break;
|
||||
case BASE_NONE:
|
||||
if (hfinfo->strings == NULL)
|
||||
if (hfinfo->strings == NULL) {
|
||||
g_error("Field '%s' (%s) is an integral value (%s)"
|
||||
" but is being displayed as BASE_NONE but"
|
||||
" without a strings conversion",
|
||||
hfinfo->name, hfinfo->abbrev,
|
||||
ftype_name(hfinfo->type));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
|
||||
g_error("Field '%s' (%s) is an integral value (%s)"
|
||||
|
@ -6715,7 +6767,7 @@ tmp_fld_check_assert(header_field_info *hfinfo)
|
|||
/* Require bytes to have a "display type" that could
|
||||
* add a character between displayed bytes.
|
||||
*/
|
||||
switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
|
||||
switch (FIELD_DISPLAY(hfinfo->display)) {
|
||||
case BASE_NONE:
|
||||
case SEP_DOT:
|
||||
case SEP_DASH:
|
||||
|
@ -6815,6 +6867,25 @@ tmp_fld_check_assert(header_field_info *hfinfo)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case FT_FLOAT:
|
||||
case FT_DOUBLE:
|
||||
if (FIELD_DISPLAY(hfinfo->display) != BASE_NONE) {
|
||||
tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
|
||||
g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
|
||||
hfinfo->name, hfinfo->abbrev,
|
||||
ftype_name(hfinfo->type),
|
||||
tmp_str);
|
||||
wmem_free(NULL, tmp_str);
|
||||
}
|
||||
if (hfinfo->bitmask != 0)
|
||||
g_error("Field '%s' (%s) is an %s but has a bitmask\n",
|
||||
hfinfo->name, hfinfo->abbrev,
|
||||
ftype_name(hfinfo->type));
|
||||
if ((hfinfo->strings != NULL) && (!(hfinfo->display & BASE_UNIT_STRING)))
|
||||
g_error("Field '%s' (%s) is an %s but has a strings value\n",
|
||||
hfinfo->name, hfinfo->abbrev,
|
||||
ftype_name(hfinfo->type));
|
||||
break;
|
||||
default:
|
||||
if (hfinfo->display != BASE_NONE) {
|
||||
tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
|
||||
|
@ -7140,10 +7211,15 @@ label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, co
|
|||
/* "%s: %s (%s)", hfinfo->name, text, descr */
|
||||
name_pos = pos = label_concat(label_str, pos, hfinfo->name);
|
||||
pos = label_concat(label_str, pos, ": ");
|
||||
pos = label_concat(label_str, pos, text ? text : "(null)");
|
||||
pos = label_concat(label_str, pos, " (");
|
||||
pos = label_concat(label_str, pos, descr ? descr : "(null)");
|
||||
pos = label_concat(label_str, pos, ")");
|
||||
if (hfinfo->display & BASE_UNIT_STRING) {
|
||||
pos = label_concat(label_str, pos, descr ? descr : "(null)");
|
||||
pos = label_concat(label_str, pos, text ? text : "(null)");
|
||||
} else {
|
||||
pos = label_concat(label_str, pos, text ? text : "(null)");
|
||||
pos = label_concat(label_str, pos, " (");
|
||||
pos = label_concat(label_str, pos, descr ? descr : "(null)");
|
||||
pos = label_concat(label_str, pos, ")");
|
||||
}
|
||||
|
||||
if (pos >= ITEM_LABEL_LENGTH) {
|
||||
/* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
|
||||
|
@ -7291,16 +7367,34 @@ proto_item_fill_label(field_info *fi, gchar *label_str)
|
|||
}
|
||||
break;
|
||||
|
||||
case FT_FLOAT:
|
||||
g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
||||
"%s: %." G_STRINGIFY(FLT_DIG) "g",
|
||||
hfinfo->name, fvalue_get_floating(&fi->value));
|
||||
case FT_FLOAT: {
|
||||
double d_value = fvalue_get_floating(&fi->value);
|
||||
if (hfinfo->display & BASE_UNIT_STRING) {
|
||||
g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
||||
"%s: %." G_STRINGIFY(FLT_DIG) "g%s",
|
||||
hfinfo->name, d_value,
|
||||
unit_name_string_get_value64((guint64)d_value, (unit_name_string*)hfinfo->strings));
|
||||
} else {
|
||||
g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
||||
"%s: %." G_STRINGIFY(FLT_DIG) "g",
|
||||
hfinfo->name, d_value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FT_DOUBLE:
|
||||
g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
||||
"%s: %." G_STRINGIFY(DBL_DIG) "g",
|
||||
hfinfo->name, fvalue_get_floating(&fi->value));
|
||||
case FT_DOUBLE: {
|
||||
double d_value = fvalue_get_floating(&fi->value);
|
||||
if (hfinfo->display & BASE_UNIT_STRING) {
|
||||
g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
||||
"%s: %." G_STRINGIFY(DBL_DIG) "g%s",
|
||||
hfinfo->name, d_value,
|
||||
unit_name_string_get_value64((guint64)d_value, (unit_name_string*)hfinfo->strings));
|
||||
} else {
|
||||
g_snprintf(label_str, ITEM_LABEL_LENGTH,
|
||||
"%s: %." G_STRINGIFY(DBL_DIG) "g",
|
||||
hfinfo->name, d_value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FT_ABSOLUTE_TIME:
|
||||
|
@ -7529,6 +7623,9 @@ hf_try_val_to_str(guint32 value, const header_field_info *hfinfo)
|
|||
if (hfinfo->display & BASE_VAL64_STRING)
|
||||
return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
|
||||
|
||||
if (hfinfo->display & BASE_UNIT_STRING)
|
||||
return unit_name_string_get_value(value, (struct unit_name_string*) hfinfo->strings);
|
||||
|
||||
return try_val_to_str(value, (const value_string *) hfinfo->strings);
|
||||
}
|
||||
|
||||
|
@ -7541,6 +7638,9 @@ hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo)
|
|||
if (hfinfo->display & BASE_RANGE_STRING)
|
||||
return try_rval64_to_str(value, (const range_string *) hfinfo->strings);
|
||||
|
||||
if (hfinfo->display & BASE_UNIT_STRING)
|
||||
return unit_name_string_get_value64(value, (struct unit_name_string*) hfinfo->strings);
|
||||
|
||||
/* If this is reached somebody registered a 64-bit field with a 32-bit
|
||||
* value-string, which isn't right. */
|
||||
DISSECTOR_ASSERT_NOT_REACHED();
|
||||
|
@ -8638,6 +8738,7 @@ proto_registrar_dump_values(void)
|
|||
const val64_string *vals64;
|
||||
const range_string *range;
|
||||
const true_false_string *tfs;
|
||||
const unit_name_string *units;
|
||||
|
||||
len = gpa_hfinfo.len;
|
||||
for (i = 0; i < len ; i++) {
|
||||
|
@ -8675,6 +8776,7 @@ proto_registrar_dump_values(void)
|
|||
vals64 = NULL;
|
||||
range = NULL;
|
||||
tfs = NULL;
|
||||
units = NULL;
|
||||
|
||||
if (hfinfo->strings != NULL) {
|
||||
if ((hfinfo->display & FIELD_DISPLAY_E_MASK) != BASE_CUSTOM &&
|
||||
|
@ -8702,6 +8804,8 @@ proto_registrar_dump_values(void)
|
|||
vals = VALUE_STRING_EXT_VS_P((value_string_ext *)hfinfo->strings);
|
||||
} else if (hfinfo->display & BASE_VAL64_STRING) {
|
||||
vals64 = (const val64_string *)hfinfo->strings;
|
||||
} else if (hfinfo->display & BASE_UNIT_STRING) {
|
||||
units = (const unit_name_string *)hfinfo->strings;
|
||||
} else {
|
||||
vals = (const value_string *)hfinfo->strings;
|
||||
}
|
||||
|
@ -8805,6 +8909,11 @@ proto_registrar_dump_values(void)
|
|||
ws_debug_printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
|
||||
tfs->true_string, tfs->false_string);
|
||||
}
|
||||
/* Print unit strings? */
|
||||
else if (units) {
|
||||
ws_debug_printf("U\t%s\t%s\t%s\n", hfinfo->abbrev,
|
||||
units->singular, units->plural ? units->plural : "(no plural)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9424,9 +9533,9 @@ proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
|
|||
hf->name, lbl);
|
||||
first = FALSE;
|
||||
}
|
||||
else if (hf->strings) {
|
||||
else if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
|
||||
proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
|
||||
hf->name, hf_try_val_to_str_const((guint32) tmpval, hf, "Unknown"));
|
||||
hf->name, hf_try_val_to_str_const((guint32) tmpval, hf, "Unknown"));
|
||||
first = FALSE;
|
||||
}
|
||||
else if (!(flags & BMT_NO_INT)) {
|
||||
|
@ -9438,7 +9547,11 @@ proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
|
|||
}
|
||||
|
||||
out = hfinfo_number_value_format(hf, buf, (guint32) tmpval);
|
||||
proto_item_append_text(item, "%s: %s", hf->name, out);
|
||||
if (hf->display & BASE_UNIT_STRING) {
|
||||
proto_item_append_text(item, "%s: %s%s", hf->name, out, unit_name_string_get_value((guint32) tmpval, (unit_name_string*)hf->strings));
|
||||
} else {
|
||||
proto_item_append_text(item, "%s: %s", hf->name, out);
|
||||
}
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
|
@ -9463,7 +9576,7 @@ proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
|
|||
hf->name, lbl);
|
||||
first = FALSE;
|
||||
}
|
||||
else if (hf->strings) {
|
||||
else if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
|
||||
proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
|
||||
hf->name, hf_try_val_to_str_const((gint32) integer32, hf, "Unknown"));
|
||||
first = FALSE;
|
||||
|
@ -9477,7 +9590,11 @@ proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
|
|||
}
|
||||
|
||||
out = hfinfo_number_value_format(hf, buf, (gint32) integer32);
|
||||
proto_item_append_text(item, "%s: %s", hf->name, out);
|
||||
if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
|
||||
proto_item_append_text(item, "%s: %s%s", hf->name, out, unit_name_string_get_value((guint32) tmpval, (unit_name_string*)hf->strings));
|
||||
} else {
|
||||
proto_item_append_text(item, "%s: %s", hf->name, out);
|
||||
}
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -546,6 +546,7 @@ typedef enum {
|
|||
#define BASE_EXT_STRING 0x200
|
||||
#define BASE_VAL64_STRING 0x400
|
||||
#define BASE_ALLOW_ZERO 0x800 /**< Display <none> instead of <MISSING> for zero sized byte array */
|
||||
#define BASE_UNIT_STRING 0x1000 /**< Add unit text to the field value */
|
||||
|
||||
/** BASE_ values that cause the field value to be displayed twice */
|
||||
#define IS_BASE_DUAL(b) ((b)==BASE_DEC_HEX||(b)==BASE_HEX_DEC)
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/* unit_strings.c
|
||||
* Units to append to field values
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <wsutil/str_util.h>
|
||||
#include "unit_strings.h"
|
||||
|
||||
char* unit_name_string_get_value(guint32 value, unit_name_string* units)
|
||||
{
|
||||
if (units->plural == NULL)
|
||||
return units->singular;
|
||||
|
||||
return plurality(value, units->singular, units->plural);
|
||||
}
|
||||
|
||||
char* unit_name_string_get_value64(guint64 value, unit_name_string* units)
|
||||
{
|
||||
if (units->plural == NULL)
|
||||
return units->singular;
|
||||
|
||||
return plurality(value, units->singular, units->plural);
|
||||
}
|
||||
|
||||
/*
|
||||
* A default set of unit strings that dissectors can use for
|
||||
* header fields. Some units intentionally have a space
|
||||
* character in them for spacing between unit and value
|
||||
*/
|
||||
const unit_name_string units_foot_feet = { " foot", " feet" };
|
||||
const unit_name_string units_bit_bits = { " bit", " bits" };
|
||||
const unit_name_string units_byte_bytes = { " byte", " bytes" };
|
||||
const unit_name_string units_word_words = { " word", " words" };
|
||||
const unit_name_string units_second_seconds = { " second", " seconds" };
|
||||
const unit_name_string units_seconds = { "s", NULL };
|
||||
const unit_name_string units_millisecond_milliseconds = { " millisecond", " milliseconds" };
|
||||
const unit_name_string units_milliseconds = { "ms", NULL };
|
||||
|
||||
/*
|
||||
* Editor modelines
|
||||
*
|
||||
* Local Variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
|
@ -0,0 +1,75 @@
|
|||
/* unit_strings.h
|
||||
* Units to append to field values
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __UNIT_STRINGS_H__
|
||||
#define __UNIT_STRINGS_H__
|
||||
|
||||
#include "ws_symbol_export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/** @file
|
||||
* Units to append to field values
|
||||
*/
|
||||
|
||||
/* For BASE_UNIT_STRING, the display format for adding units */
|
||||
typedef struct unit_name_string {
|
||||
char *singular; /* name to use for 1 unit */
|
||||
char *plural; /* name to use for < 1 or > 1 units */
|
||||
} unit_name_string;
|
||||
|
||||
WS_DLL_PUBLIC char* unit_name_string_get_value(guint32 value, unit_name_string* units);
|
||||
WS_DLL_PUBLIC char* unit_name_string_get_value64(guint64 value, unit_name_string* units);
|
||||
|
||||
/*
|
||||
* A default set of unit strings that dissectors can use for
|
||||
* header fields.
|
||||
*/
|
||||
WS_DLL_PUBLIC const unit_name_string units_foot_feet;
|
||||
WS_DLL_PUBLIC const unit_name_string units_bit_bits;
|
||||
WS_DLL_PUBLIC const unit_name_string units_byte_bytes;
|
||||
WS_DLL_PUBLIC const unit_name_string units_word_words;
|
||||
WS_DLL_PUBLIC const unit_name_string units_second_seconds; // full unit name "second[s?]"
|
||||
WS_DLL_PUBLIC const unit_name_string units_seconds; //only seconds abbreviation "s"
|
||||
WS_DLL_PUBLIC const unit_name_string units_millisecond_milliseconds; // full unit name "millisecond[s?]"
|
||||
WS_DLL_PUBLIC const unit_name_string units_milliseconds; //only seconds abbreviation "ms"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __UNIT_STRINGS_H__ */
|
||||
|
||||
/*
|
||||
* Editor modelines
|
||||
*
|
||||
* Local Variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
Loading…
Reference in New Issue