From Jakub Zawadzki:
authoretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 27 Apr 2010 10:32:34 +0000 (10:32 +0000)
committeretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 27 Apr 2010 10:32:34 +0000 (10:32 +0000)
Itroduce value_string_ext for faster value matching in value_strings.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@32574 f5534014-38df-0310-8fa8-9805f1628bb7

epan/dfilter/semcheck.c
epan/proto.c
epan/proto.h
epan/value_string.c
epan/value_string.h

index 9d8032f5e9d5f5731c42c6fb67aaa7edb7736e18..82cde98243e8d240052b56b6bee9a209b1a9d18d 100644 (file)
@@ -232,6 +232,10 @@ mk_fvalue_from_val_string(header_field_info *hfinfo, char *s)
        }
        else {
                const value_string *vals = hfinfo->strings;
+
+               if (hfinfo->display & BASE_EXT_STRING)
+                       vals = ((value_string_ext *) vals)->vals;
+
                while (vals->strptr != NULL) {
                        if (g_ascii_strcasecmp(s, vals->strptr) == 0) {
                                return mk_uint32_fvalue(vals->value);
index 9ca0d2198444fbfc90dba9047b1f2a600a3ba917..2d6761a0b84b410e34cde80ce246eaf773ab1d35 100644 (file)
@@ -3404,6 +3404,8 @@ proto_custom_set(proto_tree* tree, const int field_id, gchar *result,
                        if (hfinfo->strings) {
                                if (hfinfo->display & BASE_RANGE_STRING) {
                                        g_strlcpy(result, rval_to_str(u_integer, hfinfo->strings, "%u"), size);
+                               } else if (hfinfo->display & BASE_EXT_STRING) {
+                                       g_strlcpy(result, val_to_str_ext(u_integer, (value_string_ext *) (hfinfo->strings), "%u"), size);
                                } else {
                                        g_strlcpy(result, val_to_str(u_integer, cVALS(hfinfo->strings), "%u"), size);
                                }
@@ -3428,6 +3430,8 @@ proto_custom_set(proto_tree* tree, const int field_id, gchar *result,
                        if (hfinfo->strings) {
                                if (hfinfo->display & BASE_RANGE_STRING) {
                                        g_strlcpy(result, rval_to_str(integer, hfinfo->strings, "%d"), size);
+                               } else if (hfinfo->display & BASE_EXT_STRING) {
+                                       g_strlcpy(result, val_to_str_ext(integer, (value_string_ext *) (hfinfo->strings), "%d"), size);
                                } else {
                                        g_strlcpy(result, val_to_str(integer, cVALS(hfinfo->strings), "%d"), size);
                        }
@@ -4389,12 +4393,39 @@ static void tmp_fld_check_assert(header_field_info *hfinfo) {
        }
 }
 
+static void
+proto_reinit_value_string(value_string_ext *vse)
+{
+       const value_string *vals = vse->vals;
+       int type = VS_INDEX;
+       guint32 prev = 0;
+       guint i;
+
+       for (i = 0; i < vse->length; i++) {
+               if (type == VS_INDEX && vals[i].value != i)
+                       type = VS_BIN_TREE;
+
+               if (type == VS_BIN_TREE && prev > vals[i].value) {
+                       type = VS_SEARCH;
+                       break;
+               }
+
+               prev = vals[i].value;
+       }
+
+       vse->match_type = type;
+       printf("%p: %d\n", vse, type);
+}
+
 static int
 proto_register_field_init(header_field_info *hfinfo, const int parent)
 {
 
        tmp_fld_check_assert(hfinfo);
 
+       if (hfinfo->strings && (hfinfo->display & BASE_EXT_STRING) && IS_INT_TYPE(hfinfo->type))
+               proto_reinit_value_string((value_string_ext *) hfinfo->strings);
+
        /* if this is a bitfield, compute bitshift */
        if (hfinfo->bitmask) {
                hfinfo->bitshift = wrs_count_bitshift(hfinfo->bitmask);
@@ -4785,6 +4816,10 @@ fill_label_bitfield(field_info *fi, gchar *label_str)
                        g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
                                   format,  hfinfo->name,
                                   rval_to_str(value, hfinfo->strings, "Unknown"), value);
+               } else if (hfinfo->display & BASE_EXT_STRING) {
+                       g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
+                                format,  hfinfo->name,
+                                val_to_str_ext(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
                } else {
                        g_snprintf(p, ITEM_LABEL_LENGTH - bitfield_byte_length,
                                   format,  hfinfo->name,
@@ -4827,6 +4862,10 @@ fill_label_uint(field_info *fi, gchar *label_str)
                        g_snprintf(label_str, ITEM_LABEL_LENGTH,
                                   format,  hfinfo->name,
                                   rval_to_str(value, hfinfo->strings, "Unknown"), value);
+               } else if (hfinfo->display & BASE_EXT_STRING) {
+                       g_snprintf(label_str, ITEM_LABEL_LENGTH,
+                                format,  hfinfo->name,
+                                val_to_str_ext(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
                } else {
                        g_snprintf(label_str, ITEM_LABEL_LENGTH,
                                   format,  hfinfo->name,
@@ -4890,6 +4929,10 @@ fill_label_int(field_info *fi, gchar *label_str)
                        g_snprintf(label_str, ITEM_LABEL_LENGTH,
                                   format,  hfinfo->name,
                                   rval_to_str(value, hfinfo->strings, "Unknown"), value);
+               } else if (hfinfo->display & BASE_EXT_STRING) {
+                       g_snprintf(label_str, ITEM_LABEL_LENGTH,
+                                format,  hfinfo->name,
+                                val_to_str_ext(value, (value_string_ext *) hfinfo->strings, "Unknown"), value);
                } else {
                        g_snprintf(label_str, ITEM_LABEL_LENGTH,
                                   format,  hfinfo->name,
@@ -5765,7 +5808,9 @@ proto_registrar_dump_values(void)
                                hfinfo->type == FT_INT32 ||
                                hfinfo->type == FT_INT64)) {
 
-                               if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
+                               if ((hfinfo->display & BASE_EXT_STRING)) {
+                                       vals = ((value_string_ext *) hfinfo->strings)->vals;
+                               } if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
                                        vals = hfinfo->strings;
                                } else {
                                        range = hfinfo->strings;
@@ -6101,6 +6146,8 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
                case FT_INT32:
                        if (hfinfo->display & BASE_RANGE_STRING) {
                                str = match_strrval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
+                       } else if (hfinfo->display & BASE_EXT_STRING) {
+                               str = match_strval_ext(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
                        } else {
                                str = match_strval(fvalue_get_sinteger(&finfo->value), hfinfo->strings);
                        }
@@ -6112,6 +6159,8 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
                case FT_UINT32:
                        if (hfinfo->display & BASE_RANGE_STRING) {
                                str = match_strrval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
+                       } else if (hfinfo->display & BASE_EXT_STRING) {
+                               str = match_strval_ext(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
                        } else {
                                str = match_strval(fvalue_get_uinteger(&finfo->value), hfinfo->strings);
                        }
@@ -6398,6 +6447,9 @@ proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
                                if (hf->display & BASE_RANGE_STRING) {
                                        proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
                                                               hf->name, rval_to_str(tmpval, hf->strings, "Unknown"));
+                               } else if (hf->display & BASE_EXT_STRING) {
+                                       proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
+                                                              hf->name, val_to_str_ext(tmpval, (value_string_ext *) (hf->strings), "Unknown"));
                                } else {
                                        proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
                                                               hf->name, val_to_str(tmpval, cVALS(hf->strings), "Unknown"));
@@ -6616,6 +6668,8 @@ proto_tree_add_bits_ret_val(proto_tree *tree, const int hf_index, tvbuff_t *tvb,
                                "%s: %s (%u)",
                                str,    (hf_field->display & BASE_RANGE_STRING) ?
                                        rval_to_str((guint32)value, hf_field->strings, "Unknown ") :
+                                       (hf_field->display & BASE_EXT_STRING) ?
+                                       val_to_str_ext((guint32)value, (value_string_ext *) (hf_field->strings), "Unknown ") :
                                        val_to_str((guint32)value, cVALS(hf_field->strings), "Unknown "),
                                (guint32)value);
                        break;
index e1c8bd0048ab0f00e102bcba90f53950e799b8b0..97b934dcbaaf44e4f11ef70e306a8907ae8a86f5 100644 (file)
@@ -159,10 +159,15 @@ typedef enum {
        BASE_CUSTOM     /**< call custom routine (in ->strings) to format */
 } base_display_e;
 
+#define IS_INT_TYPE(type) \
+  ((type) == FT_UINT8 || (type) == FT_UINT16 || (type) == FT_UINT24 || (type) == FT_UINT32 || (type) == FT_UINT64 || \
+   (type) == FT_INT8 || (type) == FT_INT16 || (type) == FT_INT24 || (type) == FT_INT32 || (type) == FT_INT64)
+
 /* 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
+#define BASE_EXT_STRING 0x20
 
 /* BASE_ values that cause the field value to be displayed twice */
 #define IS_BASE_DUAL(b) ((b)==BASE_DEC_HEX||(b)==BASE_HEX_DEC)
index 0e43750c71c36eb405252a8493225a28a2052b1b..44b06478c5f161f0d54df4157bbc56296e5fd8af 100644 (file)
@@ -49,6 +49,19 @@ val_to_str(const guint32 val, const value_string *vs, const char *fmt) {
   return ep_strdup_printf(fmt, val);
 }
 
+const gchar*
+val_to_str_ext(const guint32 val, const value_string_ext *vs, const char *fmt) {
+  const gchar *ret;
+
+  g_assert(fmt != NULL);
+
+  ret = match_strval_ext(val, vs);
+  if (ret != NULL)
+    return ret;
+
+  return ep_strdup_printf(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. */
@@ -65,6 +78,19 @@ val_to_str_const(const guint32 val, const value_string *vs, const char *unknown_
   return unknown_str;
 }
 
+const gchar*
+val_to_str_ext_const(const guint32 val, const value_string_ext *vs, const char *unknown_str) {
+  const gchar *ret;
+
+  g_assert(unknown_str != NULL);
+
+  ret = match_strval_ext(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,
@@ -94,6 +120,40 @@ match_strval(const guint32 val, const value_string *vs) {
     return match_strval_idx(val, vs, &ignore_me);
 }
 
+const gchar*
+match_strval_ext(const guint32 val, const value_string_ext *vs) {
+  guint low, idx, max;
+  guint32 item;
+  if(vs) {
+    switch(vs->match_type){
+    case VS_DEFAULT: 
+      /* XXX: reinit? */
+    case VS_SEARCH:
+      return match_strval(val, vs->vals);
+    case VS_INDEX:
+      return (val < vs->length) ? vs->vals[val].strptr : NULL;
+    case VS_BIN_TREE:
+      for (low = 0, max = vs->length; low < max; ) {
+        idx = (low + max) / 2;
+        item = vs->vals[idx].value;
+
+        if (val < item)
+          max = idx;
+        else if (val > item)
+         low = idx + 1;
+        else
+          return vs->vals[idx].strptr;
+      }
+      break;
+    default:
+      g_assert_not_reached();
+      break;
+    }
+  }
+  return NULL;
+}
+
+
 /* 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. */
index 7fcbb30500131ccd70471016a4a19e1943e9a5d7..677ebb6c377202f806aff990703b5dcf300e0168 100644 (file)
@@ -34,6 +34,25 @@ typedef struct _value_string {
   const gchar   *strptr;
 } value_string;
 
+/* The way matching of value is done in a value_string:
+ * 0 default, value will be set in proto_register_field_init()
+ * 1 Sequential search (as in a normal value string)
+ * 2 The value used as an index(the value string MUST have all values 0-max defined)
+ * 3 Binary search, the valuse MUST be in numerical order.
+ */
+#define VS_DEFAULT  0 
+#define VS_SEARCH   1
+#define VS_INDEX    2
+#define VS_BIN_TREE 3
+
+typedef struct {
+  guint match_type;             /* One of the values abowe */
+  guint length;                 /* length of the array */
+  const value_string *vals;     /* the value string */
+} value_string_ext;
+
+#define VALUE_STRING_EXT_INIT(x) { VS_DEFAULT, array_length(x)-1, x }
+
 /* Struct for the str_to_str, match_strstr_idx, and match_strstr functions */
 
 typedef struct _string_string {
@@ -59,16 +78,19 @@ extern const gchar* match_strval_idx(const guint32 val, const value_string *vs,
 
 /* Like match_strval_idx(), but doesn't return the index. */
 extern const gchar* match_strval(const guint32 val, const value_string *vs);
+extern const gchar* match_strval_ext(const guint32 val, const value_string_ext *vs);
 
 /* 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. */
 extern const gchar* val_to_str(const guint32 val, const value_string *vs, const char *fmt);
+extern const gchar* val_to_str_ext(const guint32 val, const value_string_ext *vs, const char *fmt);
 
 /* 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. */
 extern const gchar* val_to_str_const(const guint32 val, const value_string *vs, const char *unknown_str);
+extern const gchar* val_to_str_ext_const(const guint32 val, const value_string_ext *vs, const char *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