Wireshark-dev: [Wireshark-dev] [PATCH] proto_tree_add_item and range_string
From: Sebastien Tandel <sebastien@xxxxxxxxx>
Date: Tue, 16 Jan 2007 20:53:45 +0100
Hi,

    Here is an updated patch for proto_tree_add_item and the
range_string structure. The new macro RVALS() can be used as the macro
VALS() in the declaration of your hf_register_info with another
structure (range_string).  Be aware that you *have to* ORed the value of
the field display with BASE_RANGE_STRING constant and it can 'only' be
used with FT_(U)INT* types in a header_field_info.


static const range_string rs_value[] = {

    {  0, 49, "Little" },
    { 50, 99, "Some" },
    {100,199, "Considerable" },
    {200,255, "High" },
    {  0,  0, NULL }
  };

proto_tree_add_item(tree, hf_proto_value, tvb, offset, 1, FALSE);

static hf_register_info hf[] = {
    { &hf_proto_value,
      { "Value", "proto.value",
        FT_UINT8, BASE_RANGE_STRING | BASE_DEC,
        RVALS(&rs_value), 0x0,
        "How much is it worth", HFILL }}
  };


+ Frame
+ Ethernet II
+ IP
+ TCP
+ Proto
  Value: High (220)




Regards,

Sebastien Tandel
Index: epan/proto.c
===================================================================
--- epan/proto.c	(révision 20453)
+++ epan/proto.c	(copie de travail)
@@ -4023,9 +4023,15 @@
 	value = fvalue_get_integer(&fi->value);
 
 	/* Fill in the textual info */
-	ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+	if (hfinfo->display & BASE_RANGE_STRING) {
+	  ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, 
 			format,  hfinfo->name,
+			rval_to_str(value, hfinfo->strings, "Unknown"), value);
+	} else {
+	  ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+			format,  hfinfo->name,
 			val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
+	}
 	if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
 		label_str[ITEM_LABEL_LENGTH - 1] = '\0';
 }
@@ -4091,9 +4097,15 @@
 	value = fvalue_get_integer(&fi->value);
 
 	/* Fill in the textual info */
-	ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+	if (hfinfo->display & BASE_RANGE_STRING) {
+	  ret = g_snprintf(label_str, ITEM_LABEL_LENGTH, 
 			format,  hfinfo->name,
+			rval_to_str(value, hfinfo->strings, "Unknown"), value);
+	} else {
+	  ret = g_snprintf(label_str, ITEM_LABEL_LENGTH,
+			format,  hfinfo->name,
 			val_to_str(value, cVALS(hfinfo->strings), "Unknown"), value);
+	}
 	if ((ret == -1) || (ret >= ITEM_LABEL_LENGTH))
 		label_str[ITEM_LABEL_LENGTH - 1] = '\0';
 }
@@ -4187,7 +4199,9 @@
 {
 	const char *format = NULL;
 
-	switch(hfinfo->display) {
+	/* bit operation to reset the potential BASE_RANGE_STRING (or others in
+	 * the future?) */
+	switch(hfinfo->display & BASE_STRUCTURE_RESET) {
 		case BASE_DEC:
 		case BASE_DEC_HEX:
 			format = "%s: %s (%u)";
@@ -4311,7 +4325,9 @@
 {
 	const char *format = NULL;
 
-	switch(hfinfo->display) {
+	/* bit operation to reset the potential BASE_RANGE_STRING (or others in
+	 * the future?)*/
+	switch(hfinfo->display & BASE_STRUCTURE_RESET) {
 		case BASE_DEC:
 		case BASE_DEC_HEX:
 			format = "%s: %s (%d)";
Index: epan/proto.h
===================================================================
--- epan/proto.h	(révision 20453)
+++ epan/proto.h	(copie de travail)
@@ -65,6 +65,10 @@
 /** Make a const true_false_string[] look like a _true_false_string pointer, used to set header_field_info.strings */
 #define TFS(x)	(const struct true_false_string*)(x)
 
+/** Make a const value_string[] look like a _value_string pointer, used to set
+ * header_field_info.strings */
+#define RVALS(x) (const struct _value_string*)(x)
+
 struct _protocol;
 
 /** Structure for information about a protocol */
@@ -129,6 +133,14 @@
     ep_strdup_printf("%s:%u: failed assertion \"%s\"", \
      file, lineno, __DISSECTOR_ASSERT_STRINGIFY(expression))))
 
+/* BASE_STRUCTURE_RESET constant is used in proto.c to reset the bits
+ * identifying special structures used in translation of value for display. 
+ * Its value means that we may have at most 16 base_display_e values */
+#define BASE_STRUCTURE_RESET 0x0F
+/* Following constants have to be ORed with a base_display_e when dissector
+ * want to use specials MACROs (for the moment, only RVALS) for a
+ * header_field_info */
+#define BASE_RANGE_STRING 0x10
 /** radix for decimal values, used in header_field_info.display */
 typedef enum {
 	BASE_NONE,	/**< none */