Huge thanks to our Platinum Members Endace and LiveAction,
and our Silver Member Veeam, for supporting the Wireshark Foundation and project.

Wireshark-dev: Re: [Wireshark-dev] RFC: sorted value_string + bsearch

From: Jakub Zawadzki <darkjames@xxxxxxxxxxxxxxxx>
Date: Tue, 27 Apr 2010 08:49:23 +0200
On Tue, Apr 27, 2010 at 08:15:35AM +0200, Anders Broman wrote:
> Can you provide an example use of the new value_string_ext as well?

Attaching sample patch for dns. Can you do some benchmarks? :)
diff --git epan/dissectors/packet-dns.c epan/dissectors/packet-dns.c
index 960231e..a814612 100644
--- epan/dissectors/packet-dns.c
+++ epan/dissectors/packet-dns.c
@@ -318,7 +318,7 @@ static const true_false_string tfs_flags_checkdisable = {
 #define OPCODE_NOTIFY   4         /* zone change notification */
 #define OPCODE_UPDATE   5         /* dynamic update */
 
-static const value_string opcode_vals[] = {
+static const value_string _opcode_vals[] = {
 	  { OPCODE_QUERY,  "Standard query"           },
 	  { OPCODE_IQUERY, "Inverse query"            },
 	  { OPCODE_STATUS, "Server status request"    },
@@ -326,6 +326,8 @@ static const value_string opcode_vals[] = {
 	  { OPCODE_UPDATE, "Dynamic update"           },
 	  { 0,              NULL                      } };
 
+static value_string_ext opcode_vals = VALUE_STRING_EXT_INIT(_opcode_vals);
+
 /* Reply codes */
 #define RCODE_NOERROR   0
 #define RCODE_FORMERR   1
@@ -339,7 +341,7 @@ static const value_string opcode_vals[] = {
 #define RCODE_NOTAUTH   9
 #define RCODE_NOTZONE   10
 
-static const value_string rcode_vals[] = {
+static const value_string _rcode_vals[] = {
 	  { RCODE_NOERROR,   "No error"             },
 	  { RCODE_FORMERR,   "Format error"         },
 	  { RCODE_SERVFAIL,  "Server failure"       },
@@ -353,6 +355,8 @@ static const value_string rcode_vals[] = {
 	  { RCODE_NOTZONE,   "Name out of zone"     },
 	  { 0,               NULL                   } };
 
+static value_string_ext rcode_vals = VALUE_STRING_EXT_INIT(_rcode_vals);
+
 #define NSEC3_HASH_RESERVED 0
 #define NSEC3_HASH_SHA1     1
 
@@ -432,7 +436,7 @@ http://www.microsoft.com/windows2000/library/resources/reskit/samplechapters/cnc
 
    which discuss them to some extent. */
 
-static const value_string dns_types[] = {
+static const value_string _dns_types[] = {
 	{ 0,		"Unused" },
 	{ T_A,		"A" },
 	{ T_NS,		"NS" },
@@ -488,8 +492,6 @@ static const value_string dns_types[] = {
 
 	{ T_HIP,        "HIP" }, /* Host Identity Protocol (HIP) RR (RFC 5205) */
 
-
-
 	{ T_SPF,	"SPF" }, /* SPF RR (RFC 4408) section 3 */ 
 	{ 100,		"UINFO" },
 	{ 101,		"UID" },
@@ -499,24 +501,26 @@ static const value_string dns_types[] = {
 	{ T_TKEY,	"TKEY"},
 	{ T_TSIG,	"TSIG"},
 
-	{ T_WINS,	"WINS"},
-	{ T_WINS_R,	"WINS-R"},
-
 	{ 251,		"IXFR"},
 	{ 252,		"AXFR"},
 	{ 253,		"MAILB"},
 	{ 254,		"MAILA"},
 	{ 255,		"ANY"},
 
-
 	{ T_DLV,        "DLV" }, /* Domain Lookaside Validation DNS Resource Record (RFC 4431) */
+
+	{ T_WINS,	"WINS"},
+	{ T_WINS_R,	"WINS-R"},
+
 	{0,		NULL}
 };
 
+static value_string_ext dns_types = VALUE_STRING_EXT_INIT(_dns_types);
+
 static const char *
 dns_type_name (guint type)
 {
-  return val_to_str(type, dns_types, "Unknown (%u)");
+  return val_to_str_ext(type, &dns_types, "Unknown (%u)");
 }
 
 static char *
@@ -628,7 +632,7 @@ dns_type_description (guint type)
     return ep_strdup(short_name);
 }
 
-static const value_string dns_classes[] = {
+static const value_string _dns_classes[] = {
 	{C_IN, "IN"},
 	{C_CS, "CS"},
 	{C_CH, "CH"},
@@ -638,10 +642,12 @@ static const value_string dns_classes[] = {
 	{0,NULL}
 };
 
+static value_string_ext dns_classes = VALUE_STRING_EXT_INIT(_dns_classes);
+
 const char *
 dns_class_name(int class)
 {
-  return val_to_str(class, dns_classes, "Unknown (%u)");
+  return val_to_str_ext(class, &dns_classes, "Unknown (%u)");
 }
 
 /* This function returns the number of bytes consumed and the expanded string
@@ -2216,7 +2222,7 @@ dissect_dns_answer(tvbuff_t *tvb, int offsetx, int dns_data_offset,
 	  goto bad_rr;
 	tkey_error = tvb_get_ntohs(tvb, cur_offset);
         proto_tree_add_text(rr_tree, tvb, cur_offset, 2, "Error: %s",
-		val_to_str(tkey_error, rcode_vals,
+		val_to_str_ext(tkey_error, &rcode_vals,
 		val_to_str(tkey_error, tsigerror_vals, "Unknown error (%x)")));
 	cur_offset += 2;
 	rr_len -= 2;
@@ -2366,7 +2372,7 @@ dissect_dns_answer(tvbuff_t *tvb, int offsetx, int dns_data_offset,
 	  goto bad_rr;
 	tsig_error = tvb_get_ntohs(tvb, cur_offset);
 	proto_tree_add_uint_format(rr_tree, hf_dns_tsig_error, tvb, cur_offset, 2, tsig_error, "Error: %s (%d)",
-		val_to_str(tsig_error, rcode_vals,val_to_str(tsig_error, tsigerror_vals, "Unknown error")),
+		val_to_str_ext(tsig_error, &rcode_vals,val_to_str(tsig_error, tsigerror_vals, "Unknown error")),
 		tsig_error);
 	cur_offset += 2;
 	rr_len -= 2;
@@ -3067,14 +3073,14 @@ dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
     bufpos=0;
     bufpos+=MIN(MAX_BUF_SIZE-bufpos,
 		g_snprintf(buf+bufpos, MAX_BUF_SIZE-bufpos, "%s%s",
-		val_to_str(opcode, opcode_vals, "Unknown operation (%u)"),
+		val_to_str_ext(opcode, &opcode_vals, "Unknown operation (%u)"),
 		(flags&F_RESPONSE)?" response":""));
 
     if (flags & F_RESPONSE) {
       if ((flags & F_RCODE) != RCODE_NOERROR) {
 	bufpos+=MIN(MAX_BUF_SIZE-bufpos,
 		    g_snprintf(buf+bufpos, MAX_BUF_SIZE-bufpos, ", %s",
-			val_to_str(flags & F_RCODE, rcode_vals, "Unknown error (%u)")));
+			val_to_str_ext(flags & F_RCODE, &rcode_vals, "Unknown error (%u)")));
       }
     }
     col_add_str(pinfo->cinfo, COL_INFO, buf);
@@ -3189,11 +3195,11 @@ dissect_dns_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
   bufpos=0;
   bufpos+=MIN(MAX_BUF_SIZE-bufpos,
 		g_snprintf(buf+bufpos, MAX_BUF_SIZE-bufpos, "%s",
-		val_to_str(opcode, opcode_vals, "Unknown operation")));
+		val_to_str_ext(opcode, &opcode_vals, "Unknown operation")));
   if (flags & F_RESPONSE) {
     bufpos+=MIN(MAX_BUF_SIZE-bufpos,
 		g_snprintf(buf+bufpos, MAX_BUF_SIZE-bufpos, " response, %s",
-		val_to_str(flags & F_RCODE, rcode_vals, "Unknown error")));
+		val_to_str_ext(flags & F_RCODE, &rcode_vals, "Unknown error")));
   }
   tf = proto_tree_add_uint_format(dns_tree, hf_dns_flags, tvb,
 		offset + DNS_FLAGS, 2,
@@ -3402,7 +3408,7 @@ proto_register_dns(void)
 	"Is the message a response?", HFILL }},
     { &hf_dns_flags_opcode,
       { "Opcode",		"dns.flags.opcode",
-	FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
+	FT_UINT16, BASE_DEC | BASE_EXT_STRING, VALS(&opcode_vals), F_OPCODE,
 	"Operation code", HFILL }},
     { &hf_dns_flags_authoritative,
       { "Authoritative",	"dns.flags.authoritative",
@@ -3446,7 +3452,7 @@ proto_register_dns(void)
 	"Is non-authenticated data acceptable?", HFILL }},
     { &hf_dns_flags_rcode,
       { "Reply code",		"dns.flags.rcode",
-	FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
+	FT_UINT16, BASE_DEC | BASE_EXT_STRING, VALS(&rcode_vals), F_RCODE,
 	NULL, HFILL }},
     { &hf_dns_transaction_id,
       { "Transaction ID",      	"dns.id",
@@ -3454,15 +3460,15 @@ proto_register_dns(void)
 	"Identification of transaction", HFILL }},
     { &hf_dns_qry_type,
       { "Type",      	"dns.qry.type",
-	FT_UINT16, BASE_HEX, VALS(dns_types), 0x0,
+	FT_UINT16, BASE_HEX | BASE_EXT_STRING, VALS(&dns_types), 0x0,
 	"Query Type", HFILL }},
     { &hf_dns_qry_class,
       { "Class",      	"dns.qry.class",
-	FT_UINT16, BASE_HEX, VALS(dns_classes), 0x0,
+	FT_UINT16, BASE_HEX | BASE_EXT_STRING, VALS(&dns_classes), 0x0,
 	"Query Class", HFILL }},
     { &hf_dns_qry_class_mdns,
       { "Class",      	"dns.qry.class",
-	FT_UINT16, BASE_HEX, VALS(dns_classes), 0x7FFF,
+	FT_UINT16, BASE_HEX | BASE_EXT_STRING, VALS(&dns_classes), 0x7FFF,
 	"Query Class", HFILL }},
     { &hf_dns_qry_qu,
       { "\"QU\" question", 	"dns.qry.qu",
@@ -3474,15 +3480,15 @@ proto_register_dns(void)
 	"Query Name", HFILL }},
     { &hf_dns_rr_type,
       { "Type",      	"dns.resp.type",
-	FT_UINT16, BASE_HEX, VALS(dns_types), 0x0,
+	FT_UINT16, BASE_HEX | BASE_EXT_STRING, VALS(&dns_types), 0x0,
 	"Response Type", HFILL }},
     { &hf_dns_rr_class,
       { "Class",      	"dns.resp.class",
-	FT_UINT16, BASE_HEX, VALS(dns_classes), 0x0,
+	FT_UINT16, BASE_HEX | BASE_EXT_STRING, VALS(&dns_classes), 0x0,
 	"Response Class", HFILL }},
     { &hf_dns_rr_class_mdns,
       { "Class",      	"dns.resp.class",
-	FT_UINT16, BASE_HEX, VALS(dns_classes), 0x7FFF,
+	FT_UINT16, BASE_HEX | BASE_EXT_STRING, VALS(&dns_classes), 0x7FFF,
 	"Response Class", HFILL }},
     { &hf_dns_rr_cache_flush,
       { "Cache flush", 	"dns.resp.cache_flush",