static const char* hfinfo_int_format(const header_field_info *hfinfo);
static const char* hfinfo_int_value_format(const header_field_info *hfinfo);
static const char* hfinfo_int64_format(const header_field_info *hfinfo);
+static const char* hfinfo_numeric_value_format(const header_field_info *hfinfo);
static proto_item *
proto_tree_add_node(proto_tree *tree, field_info *fi);
static void
proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
static void
-proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gboolean little_endian);
+proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
static void
proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
static void
static void
proto_tree_set_uint64(field_info *fi, guint64 value);
static void
-proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, gboolean little_endian);
+proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
static gboolean
proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
const int len, const gint ett, const gint **fields,
*/
proto_tree *
ptvcursor_add_with_subtree(ptvcursor_t * ptvc, int hfindex, gint length,
- gboolean little_endian, gint ett_subtree)
+ const guint encoding, gint ett_subtree)
{
proto_item * it;
- it = ptvcursor_add_no_advance(ptvc, hfindex, length, little_endian);
+ it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
}
pi = proto_tree_add_text_node(tree, NULL, 0, 0);
- va_start(ap, format);
- if (pi)
+ if (pi) {
+ va_start(ap, format);
proto_tree_set_representation(pi, format, ap);
+ va_end(ap);
+ }
+ va_start(ap, format);
vprintf(format, ap);
va_end(ap);
printf("\n");
return pi;
}
-
+/*
+ * NOTE: to support code written when proto_tree_add_item() took a
+ * gboolean as its last argument, with FALSE meaning "big-endian"
+ * and TRUE meaning "little-endian", we treat any non-zero value of
+ * "encoding" as meaning "little-endian".
+ */
static guint32
-get_uint_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
+get_uint_value(tvbuff_t *tvb, gint offset, gint length, const guint encoding)
{
guint32 value;
break;
case 2:
- value = little_endian ? tvb_get_letohs(tvb, offset)
- : tvb_get_ntohs(tvb, offset);
+ value = encoding ? tvb_get_letohs(tvb, offset)
+ : tvb_get_ntohs(tvb, offset);
break;
case 3:
- value = little_endian ? tvb_get_letoh24(tvb, offset)
- : tvb_get_ntoh24(tvb, offset);
+ value = encoding ? tvb_get_letoh24(tvb, offset)
+ : tvb_get_ntoh24(tvb, offset);
break;
case 4:
- value = little_endian ? tvb_get_letohl(tvb, offset)
- : tvb_get_ntohl(tvb, offset);
+ value = encoding ? tvb_get_letohl(tvb, offset)
+ : tvb_get_ntohl(tvb, offset);
break;
default:
return value;
}
+/*
+ * NOTE: to support code written when proto_tree_add_item() took a
+ * gboolean as its last argument, with FALSE meaning "big-endian"
+ * and TRUE meaning "little-endian", we treat any non-zero value of
+ * "encoding" as meaning "little-endian".
+ */
static gint32
-get_int_value(tvbuff_t *tvb, gint offset, gint length, gboolean little_endian)
+get_int_value(tvbuff_t *tvb, gint offset, gint length, const guint encoding)
{
gint32 value;
break;
case 2:
- value = (gint16) (little_endian ? tvb_get_letohs(tvb, offset)
- : tvb_get_ntohs(tvb, offset));
+ value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
+ : tvb_get_ntohs(tvb, offset));
break;
case 3:
- value = little_endian ? tvb_get_letoh24(tvb, offset)
- : tvb_get_ntoh24(tvb, offset);
+ value = encoding ? tvb_get_letoh24(tvb, offset)
+ : tvb_get_ntoh24(tvb, offset);
if (value & 0x00800000) {
/* Sign bit is set; sign-extend it. */
value |= 0xFF000000;
break;
case 4:
- value = little_endian ? tvb_get_letohl(tvb, offset)
- : tvb_get_ntohl(tvb, offset);
+ value = encoding ? tvb_get_letohl(tvb, offset)
+ : tvb_get_ntohl(tvb, offset);
break;
default:
static proto_item *
proto_tree_new_item(field_info *new_fi, proto_tree *tree,
tvbuff_t *tvb, gint start, gint length,
- gboolean little_endian)
+ const guint encoding)
{
proto_item *pi;
guint32 value, n;
float floatval;
double doubleval;
char *string;
+ nstime_t time_stamp;
GPtrArray *ptrs;
/* there is a possibility here that we might raise an exception
break;
case FT_UINT_BYTES:
- n = get_uint_value(tvb, start, length, little_endian);
+ n = get_uint_value(tvb, start, length, encoding);
proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
/* Instead of calling proto_item_set_len(), since we don't yet
case FT_BOOLEAN:
proto_tree_set_boolean(new_fi,
- get_uint_value(tvb, start, length, little_endian));
+ get_uint_value(tvb, start, length, encoding));
break;
/* XXX - make these just FT_UINT? */
case FT_UINT24:
case FT_UINT32:
proto_tree_set_uint(new_fi,
- get_uint_value(tvb, start, length, little_endian));
+ get_uint_value(tvb, start, length, encoding));
break;
case FT_INT64:
case FT_UINT64:
DISSECTOR_ASSERT( length <= 8 && length >= 1);
- proto_tree_set_uint64_tvb(new_fi, tvb, start, length, little_endian);
+ proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
break;
/* XXX - make these just FT_INT? */
case FT_INT24:
case FT_INT32:
proto_tree_set_int(new_fi,
- get_int_value(tvb, start, length, little_endian));
+ get_int_value(tvb, start, length, encoding));
break;
case FT_IPv4:
DISSECTOR_ASSERT(length == FT_IPv4_LEN);
value = tvb_get_ipv4(tvb, start);
- proto_tree_set_ipv4(new_fi, little_endian ? GUINT32_SWAP_LE_BE(value) : value);
+ /*
+ * NOTE: to support code written when
+ * proto_tree_add_item() took a gboolean as its
+ * last argument, with FALSE meaning "big-endian"
+ * and TRUE meaning "little-endian", we treat any
+ * non-zero value of "encoding" as meaning
+ * "little-endian".
+ */
+ proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
break;
case FT_IPXNET:
case FT_GUID:
DISSECTOR_ASSERT(length == FT_GUID_LEN);
- proto_tree_set_guid_tvb(new_fi, tvb, start, little_endian);
+ proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
break;
case FT_OID:
case FT_FLOAT:
DISSECTOR_ASSERT(length == 4);
- if (little_endian)
+ /*
+ * NOTE: to support code written when
+ * proto_tree_add_item() took a gboolean as its
+ * last argument, with FALSE meaning "big-endian"
+ * and TRUE meaning "little-endian", we treat any
+ * non-zero value of "encoding" as meaning
+ * "little-endian".
+ *
+ * At some point in the future, we might
+ * support non-IEEE-binary floating-point
+ * formats in the encoding as well
+ * (IEEE decimal, System/3x0, VAX).
+ */
+ if (encoding)
floatval = tvb_get_letohieee_float(tvb, start);
else
floatval = tvb_get_ntohieee_float(tvb, start);
break;
case FT_DOUBLE:
+ /*
+ * NOTE: to support code written when
+ * proto_tree_add_item() took a gboolean as its
+ * last argument, with FALSE meaning "big-endian"
+ * and TRUE meaning "little-endian", we treat any
+ * non-zero value of "encoding" as meaning
+ * "little-endian".
+ *
+ * At some point in the future, we might
+ * support non-IEEE-binary floating-point
+ * formats in the encoding as well
+ * (IEEE decimal, System/3x0, VAX).
+ */
DISSECTOR_ASSERT(length == 8);
- if (little_endian)
+ if (encoding)
doubleval = tvb_get_letohieee_double(tvb, start);
else
doubleval = tvb_get_ntohieee_double(tvb, start);
break;
case FT_UINT_STRING:
- n = get_uint_value(tvb, start, length, little_endian);
+ n = get_uint_value(tvb, start, length, encoding);
proto_tree_set_string_tvb(new_fi, tvb, start + length, n);
/* Instead of calling proto_item_set_len(), since we
new_fi->length = n + length;
break;
+ case FT_ABSOLUTE_TIME:
+ case FT_RELATIVE_TIME:
+ DISSECTOR_ASSERT(length == 8 || length == 4);
+ /*
+ * NOTE: to support code written when
+ * proto_tree_add_item() took a gboolean as its
+ * last argument, with FALSE meaning "big-endian"
+ * and TRUE meaning "little-endian", we treat any
+ * non-zero value of "encoding" as meaning
+ * "little-endian".
+ *
+ * At some point in the future, we might
+ * support non-struct timespec formats in
+ * the encoding as well (struct timeval,
+ * NTP time, Windows NT FILETIME, time_t, etc.).
+ */
+ if (encoding) {
+ time_stamp.secs = tvb_get_letohl(tvb, start);
+ if (length == 8)
+ time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
+ else
+ time_stamp.nsecs = 0;
+ } else {
+ time_stamp.secs = tvb_get_ntohl(tvb, start);
+ if (length == 8)
+ time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
+ else
+ time_stamp.nsecs = 0;
+ }
+ proto_tree_set_time(new_fi, &time_stamp);
+ break;
+
default:
g_error("new_fi->hfinfo->type %d (%s) not handled\n",
new_fi->hfinfo->type,
DISSECTOR_ASSERT_NOT_REACHED();
break;
}
- FI_SET_FLAG(new_fi, (little_endian) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
+ /*
+ * XXX - this should just check the ENC_*_ENDIAN bit, with
+ * those fields for which we treat any non-zero value of
+ * "encoding" checking the rest of the bits.
+ */
+ FI_SET_FLAG(new_fi, (encoding) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
/* Don't add new node to proto_tree until now so that any exceptions
* raised by a tvbuff access method doesn't leave junk in the proto_tree. */
and returns proto_item* */
proto_item *
ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
- gboolean little_endian)
+ const guint encoding)
{
field_info *new_fi;
header_field_info *hfinfo;
* The length of the rest of the item is in the first N
* bytes of the item.
*/
- n = get_uint_value(ptvc->tvb, offset, length, little_endian);
+ n = get_uint_value(ptvc->tvb, offset, length, encoding);
ptvc->offset += n;
}
return NULL;
return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
- offset, length, little_endian);
+ offset, length, encoding);
}
/* Add an item to a proto_tree, using the text label registered to that item;
the item is extracted from the tvbuff handed to it. */
proto_item *
proto_tree_add_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
- const gint start, gint length, const gboolean little_endian)
+ const gint start, gint length, const guint encoding)
{
field_info *new_fi;
header_field_info *hfinfo;
return(NULL);
return proto_tree_new_item(new_fi, tree, tvb, start,
- length, little_endian);
+ length, encoding);
}
/* Add a FT_NONE to a proto_tree */
* offset, and returns proto_item* */
proto_item *
ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
- gboolean endianness)
+ const guint encoding)
{
proto_item *item;
item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
- length, endianness);
+ length, encoding);
return item;
}
static void
proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
- gboolean little_endian)
+ const guint encoding)
{
e_guid_t guid;
- tvb_get_guid(tvb, start, &guid, little_endian);
+ tvb_get_guid(tvb, start, &guid, encoding);
proto_tree_set_guid(fi, &guid);
}
fvalue_set_integer64(&fi->value, value);
}
+/*
+ * NOTE: to support code written when proto_tree_add_item() took a
+ * gboolean as its last argument, with FALSE meaning "big-endian"
+ * and TRUE meaning "little-endian", we treat any non-zero value of
+ * "encoding" as meaning "little-endian".
+ */
static void
proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
- guint length, gboolean little_endian)
+ guint length, const guint encoding)
{
guint64 value = 0;
guint8* b = ep_tvb_memdup(tvb,start,length);
- if(little_endian) {
+ if(encoding) {
b += length;
switch(length) {
default: DISSECTOR_ASSERT_NOT_REACHED();
/* -------------------------- */
const gchar *
-proto_custom_set(proto_tree* tree, const int field_id, gchar *result,
- gchar *expr, const int size)
+proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
+ gchar *result, gchar *expr, const int size)
{
guint32 u_integer;
gint32 integer;
guint32 n_addr; /* network-order IPv4 address */
const true_false_string *tfstring;
- int len;
+ int len, prev_len=0, last, i, offset_r=0, offset_e=0;
GPtrArray *finfos;
- field_info *finfo;
+ field_info *finfo = NULL;
header_field_info* hfinfo;
+ const gchar *abbrev = NULL;
g_assert(field_id >= 0);
if (!hfinfo)
return "";
+ if (occurrence < 0) {
+ /* Search other direction */
+ while (hfinfo->same_name_prev) {
+ hfinfo = hfinfo->same_name_prev;
+ }
+ }
+
while (hfinfo) {
finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
if (!finfos || !(len = g_ptr_array_len(finfos))) {
- hfinfo = hfinfo->same_name_next;
- continue;
- }
- /* get the last one */
- finfo = g_ptr_array_index(finfos, len -1);
-
- switch(hfinfo->type) {
-
- case FT_NONE: /* Nothing to add */
- result[0] = '\0';
- break;
-
- case FT_PROTOCOL:
- g_strlcpy(result, "Yes", size);
- break;
-
- case FT_UINT_BYTES:
- case FT_BYTES:
- bytes = fvalue_get(&finfo->value);
- g_strlcpy(result, bytes_to_str(bytes, fvalue_length(&finfo->value)), size);
- break;
-
- case FT_ABSOLUTE_TIME:
- g_strlcpy(result,
- abs_time_to_str(fvalue_get(&finfo->value), hfinfo->display),
- size);
- break;
-
- case FT_RELATIVE_TIME:
- g_strlcpy(result, rel_time_to_secs_str(fvalue_get(&finfo->value)), size);
- break;
-
- case FT_BOOLEAN:
- u_integer = fvalue_get_uinteger(&finfo->value);
- tfstring = (const true_false_string *)&tfs_true_false;
- if (hfinfo->strings) {
- tfstring = (const struct true_false_string*) hfinfo->strings;
- }
- g_strlcpy(result, u_integer ? tfstring->true_string : tfstring->false_string, size);
- break;
-
- case FT_UINT8:
- case FT_UINT16:
- case FT_UINT24:
- case FT_UINT32:
- case FT_FRAMENUM:
- u_integer = fvalue_get_uinteger(&finfo->value);
- 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);
- }
- } else if (IS_BASE_DUAL(hfinfo->display)) {
- g_snprintf(result, size, hfinfo_uint_value_format(hfinfo), u_integer, u_integer);
+ if (occurrence < 0) {
+ hfinfo = hfinfo->same_name_next;
} else {
- g_snprintf(result, size, hfinfo_uint_value_format(hfinfo), u_integer);
+ hfinfo = hfinfo->same_name_prev;
}
- break;
-
- case FT_INT64:
- case FT_UINT64:
- g_snprintf(result, size, "%" G_GINT64_MODIFIER "u", fvalue_get_integer64(&finfo->value));
- break;
-
- /* XXX - make these just FT_INT? */
- case FT_INT8:
- case FT_INT16:
- case FT_INT24:
- case FT_INT32:
- integer = fvalue_get_sinteger(&finfo->value);
- 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);
- }
- } else if (IS_BASE_DUAL(hfinfo->display)) {
- g_snprintf(result, size, hfinfo_int_value_format(hfinfo), integer, integer);
- } else {
- g_snprintf(result, size, hfinfo_int_value_format(hfinfo), integer);
- }
- break;
-
- case FT_IPv4:
- ipv4 = fvalue_get(&finfo->value);
- n_addr = ipv4_get_net_order_addr(ipv4);
- g_strlcpy(result, ip_to_str((guint8 *)&n_addr), size);
- break;
-
- case FT_IPv6:
- ipv6 = fvalue_get(&finfo->value);
- SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
- address_to_str_buf(&addr, result, size);
- break;
-
- case FT_ETHER:
- g_strlcpy(result, bytes_to_str_punct(fvalue_get(&finfo->value), 6, ':'), size);
- break;
-
- case FT_GUID:
- g_strlcpy(result, guid_to_str((e_guid_t *)fvalue_get(&finfo->value)), size);
- break;
-
- case FT_OID:
- bytes = fvalue_get(&finfo->value);
- g_strlcpy(result, oid_resolved_from_encoded(bytes, fvalue_length(&finfo->value)), size);
- break;
-
- case FT_FLOAT:
- g_snprintf(result, size, "%." STRINGIFY(FLT_DIG) "f", fvalue_get_floating(&finfo->value));
- break;
-
- case FT_DOUBLE:
- g_snprintf(result, size, "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
- break;
-
- case FT_EBCDIC:
- case FT_STRING:
- case FT_STRINGZ:
- case FT_UINT_STRING:
- bytes = fvalue_get(&finfo->value);
- g_strlcpy(result, format_text(bytes, strlen(bytes)), size);
- break;
-
- case FT_IPXNET: /*XXX really No column custom ?*/
- case FT_PCRE:
- default:
- g_error("hfinfo->type %d (%s) not handled\n",
- hfinfo->type,
- ftype_name(hfinfo->type));
- DISSECTOR_ASSERT_NOT_REACHED();
- break;
+ continue;
}
- switch(hfinfo->type) {
- case FT_EBCDIC:
- case FT_STRING:
- case FT_STRINGZ:
- case FT_UINT_STRING:
- g_snprintf(expr, size, "\"%s\"",result);
- default:
- g_strlcpy(expr, result, size);
- break;
- }
- return hfinfo->abbrev;
- }
- return "";
+ /* Are there enough occurrences of the field? */
+ if ((occurrence-prev_len > len) || (occurrence+prev_len < -len)) {
+ if (occurrence < 0) {
+ hfinfo = hfinfo->same_name_next;
+ } else {
+ hfinfo = hfinfo->same_name_prev;
+ }
+ prev_len += len;
+ continue;
+ }
+
+ /* Calculate single index or set outer bounderies */
+ if (occurrence < 0) {
+ i = occurrence + len + prev_len;
+ last = i;
+ } else if (occurrence > 0) {
+ i = occurrence - 1 - prev_len;
+ last = i;
+ } else {
+ i = 0;
+ last = len - 1;
+ }
+
+ prev_len += len; /* Count handled occurrences */
+
+ while (i <= last) {
+ finfo = g_ptr_array_index(finfos, i);
+
+ if (offset_r && (offset_r < size-2))
+ result[offset_r++]=',';
+
+ if (offset_e && (offset_e < size-2))
+ expr[offset_e++]=',';
+
+ switch(hfinfo->type) {
+
+ case FT_NONE: /* Nothing to add */
+ if (offset_r == 0) {
+ result[0] = '\0';
+ } else if (result[offset_r-1] == ',') {
+ result[offset_r-1] = '\0';
+ }
+ break;
+
+ case FT_PROTOCOL:
+ /* prevent multiple "yes" entries by setting result directly */
+ g_strlcpy(result, "Yes", size);
+ break;
+
+ case FT_UINT_BYTES:
+ case FT_BYTES:
+ bytes = fvalue_get(&finfo->value);
+ offset_r += (int)g_strlcpy(result+offset_r, bytes_to_str(bytes, fvalue_length(&finfo->value)), size-offset_r);
+ break;
+
+ case FT_ABSOLUTE_TIME:
+ offset_r += (int)g_strlcpy(result+offset_r,
+ abs_time_to_str(fvalue_get(&finfo->value), hfinfo->display, TRUE),
+ size-offset_r);
+ break;
+
+ case FT_RELATIVE_TIME:
+ offset_r += (int)g_strlcpy(result+offset_r, rel_time_to_secs_str(fvalue_get(&finfo->value)), size-offset_r);
+ break;
+
+ case FT_BOOLEAN:
+ u_integer = fvalue_get_uinteger(&finfo->value);
+ tfstring = (const true_false_string *)&tfs_true_false;
+ if (hfinfo->strings) {
+ tfstring = (const struct true_false_string*) hfinfo->strings;
+ }
+ offset_r += (int)g_strlcpy(result+offset_r, u_integer ? tfstring->true_string : tfstring->false_string, size-offset_r);
+
+ g_snprintf(expr+offset_e, size-offset_e, "%u", fvalue_get_uinteger(&finfo->value) ? 1 : 0);
+ offset_e = (int)strlen(expr);
+ break;
+
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ case FT_FRAMENUM:
+ u_integer = fvalue_get_uinteger(&finfo->value);
+ if (hfinfo->strings) {
+ if (hfinfo->display & BASE_RANGE_STRING) {
+ offset_r += (int)g_strlcpy(result+offset_r, rval_to_str(u_integer, hfinfo->strings, "%u"), size-offset_r);
+ } else if (hfinfo->display & BASE_EXT_STRING) {
+ offset_r += (int)g_strlcpy(result+offset_r, val_to_str_ext(u_integer, (value_string_ext *) (hfinfo->strings), "%u"), size-offset_r);
+ } else {
+ offset_r += (int)g_strlcpy(result+offset_r, val_to_str(u_integer, cVALS(hfinfo->strings), "%u"), size-offset_r);
+ }
+ } else if (IS_BASE_DUAL(hfinfo->display)) {
+ g_snprintf(result+offset_r, size-offset_r, hfinfo_uint_value_format(hfinfo), u_integer, u_integer);
+ offset_r = (int)strlen(result);
+ } else {
+ g_snprintf(result+offset_r, size-offset_r, hfinfo_uint_value_format(hfinfo), u_integer);
+ offset_r = (int)strlen(result);
+ }
+
+ g_snprintf(expr+offset_e, size-offset_e, hfinfo_numeric_value_format(hfinfo), fvalue_get_uinteger(&finfo->value));
+ offset_e = (int)strlen(expr);
+ break;
+
+ case FT_INT64:
+ case FT_UINT64:
+ g_snprintf(result+offset_r, size-offset_r, "%" G_GINT64_MODIFIER "u", fvalue_get_integer64(&finfo->value));
+ offset_r = (int)strlen(result);
+ break;
+
+ /* XXX - make these just FT_INT? */
+ case FT_INT8:
+ case FT_INT16:
+ case FT_INT24:
+ case FT_INT32:
+ integer = fvalue_get_sinteger(&finfo->value);
+ if (hfinfo->strings) {
+ if (hfinfo->display & BASE_RANGE_STRING) {
+ offset_r += (int)g_strlcpy(result+offset_r, rval_to_str(integer, hfinfo->strings, "%d"), size-offset_r);
+ } else if (hfinfo->display & BASE_EXT_STRING) {
+ offset_r += (int)g_strlcpy(result+offset_r, val_to_str_ext(integer, (value_string_ext *) (hfinfo->strings), "%d"), size-offset_r);
+ } else {
+ offset_r += (int)g_strlcpy(result+offset_r, val_to_str(integer, cVALS(hfinfo->strings), "%d"), size-offset_r);
+ }
+ } else if (IS_BASE_DUAL(hfinfo->display)) {
+ g_snprintf(result+offset_r, size-offset_r, hfinfo_int_value_format(hfinfo), integer, integer);
+ offset_r = (int)strlen(result);
+ } else {
+ g_snprintf(result+offset_r, size-offset_r, hfinfo_int_value_format(hfinfo), integer);
+ offset_r = (int)strlen(result);
+ }
+
+ g_snprintf(expr+offset_e, size-offset_e, hfinfo_numeric_value_format(hfinfo), fvalue_get_sinteger(&finfo->value));
+ offset_e = (int)strlen(expr);
+ break;
+
+ case FT_IPv4:
+ ipv4 = fvalue_get(&finfo->value);
+ n_addr = ipv4_get_net_order_addr(ipv4);
+ offset_r += (int)g_strlcpy(result+offset_r, ip_to_str((guint8 *)&n_addr), size-offset_r);
+ break;
+
+ case FT_IPv6:
+ ipv6 = fvalue_get(&finfo->value);
+ SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
+ address_to_str_buf(&addr, result+offset_r, size-offset_r);
+ offset_r = (int)strlen(result);
+ break;
+
+ case FT_ETHER:
+ offset_r += (int)g_strlcpy(result+offset_r, bytes_to_str_punct(fvalue_get(&finfo->value), 6, ':'), size-offset_r);
+ break;
+
+ case FT_GUID:
+ offset_r += (int)g_strlcpy(result+offset_r, guid_to_str((e_guid_t *)fvalue_get(&finfo->value)), size-offset_r);
+ break;
+
+ case FT_OID:
+ bytes = fvalue_get(&finfo->value);
+ offset_r += (int)g_strlcpy(result+offset_r, oid_resolved_from_encoded(bytes, fvalue_length(&finfo->value)), size-offset_r);
+ offset_e += (int)g_strlcpy(expr+offset_e, oid_encoded2string(bytes, fvalue_length(&finfo->value)), size-offset_e);
+ break;
+
+ case FT_FLOAT:
+ g_snprintf(result+offset_r, size-offset_r, "%." STRINGIFY(FLT_DIG) "f", fvalue_get_floating(&finfo->value));
+ offset_r = (int)strlen(result);
+ break;
+
+ case FT_DOUBLE:
+ g_snprintf(result+offset_r, size-offset_r, "%." STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
+ offset_r = (int)strlen(result);
+ break;
+
+ case FT_EBCDIC:
+ case FT_STRING:
+ case FT_STRINGZ:
+ case FT_UINT_STRING:
+ bytes = fvalue_get(&finfo->value);
+ offset_r += (int)g_strlcpy(result+offset_r, format_text(bytes, strlen(bytes)), size-offset_r);
+ break;
+
+ case FT_IPXNET: /*XXX really No column custom ?*/
+ case FT_PCRE:
+ default:
+ g_error("hfinfo->type %d (%s) not handled\n",
+ hfinfo->type,
+ ftype_name(hfinfo->type));
+ DISSECTOR_ASSERT_NOT_REACHED();
+ break;
+ }
+ i++;
+ }
+
+ switch(hfinfo->type) {
+
+ case FT_BOOLEAN:
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ case FT_FRAMENUM:
+ case FT_INT8:
+ case FT_INT16:
+ case FT_INT24:
+ case FT_INT32:
+ case FT_OID:
+ /* for these types, "expr" is filled in the loop above */
+ break;
+
+ default:
+ /* for all others, just copy "result" to "expr" */
+ g_strlcpy(expr, result, size);
+ break;
+ }
+
+ if (!abbrev) {
+ /* Store abbrev for return value */
+ abbrev = hfinfo->abbrev;
+ }
+
+ if (occurrence == 0) {
+ /* Fetch next hfinfo with same name (abbrev) */
+ hfinfo = hfinfo->same_name_prev;
+ } else {
+ hfinfo = NULL;
+ }
+ }
+
+ return abbrev ? abbrev : "";
}
}
if (!PROTO_ITEM_IS_HIDDEN(pi)) {
- va_start(ap, format);
-
/*
* If we don't already have a representation,
* generate the default representation.
curlen = strlen(fi->rep->representation);
if (ITEM_LABEL_LENGTH > curlen) {
+ va_start(ap, format);
g_vsnprintf(fi->rep->representation + curlen,
ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
+ va_end(ap);
}
+ }
+}
+
+/* Prepend to text of proto_item after having already been created. */
+void
+proto_item_prepend_text(proto_item *pi, const char *format, ...)
+{
+ field_info *fi = NULL;
+ char representation[ITEM_LABEL_LENGTH];
+ size_t curlen;
+ va_list ap;
+
+ if (pi==NULL) {
+ return;
+ }
+
+ fi = PITEM_FINFO(pi);
+ if (fi==NULL) {
+ return;
+ }
+
+ if (!PROTO_ITEM_IS_HIDDEN(pi)) {
+ /*
+ * If we don't already have a representation,
+ * generate the default representation.
+ */
+ if (fi->rep == NULL) {
+ ITEM_LABEL_NEW(fi->rep);
+ proto_item_fill_label(fi, fi->rep->representation);
+ }
+
+ strcpy(representation, fi->rep->representation);
+ va_start(ap, format);
+ g_vsnprintf(fi->rep->representation,
+ ITEM_LABEL_LENGTH, format, ap);
va_end(ap);
+ curlen = strlen(fi->rep->representation);
+ if (ITEM_LABEL_LENGTH > curlen) {
+ strncpy(fi->rep->representation + curlen, representation,
+ ITEM_LABEL_LENGTH - (gulong) curlen);
+ }
}
}
/* if we always add and never delete, then id == len - 1 is correct */
if(gpa_hfinfo.len>=gpa_hfinfo.allocated_len){
if(!gpa_hfinfo.hfi){
- gpa_hfinfo.allocated_len=1000;
- gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*1000);
+ gpa_hfinfo.allocated_len=100000;
+ gpa_hfinfo.hfi=g_malloc(sizeof(header_field_info *)*100000);
} else {
gpa_hfinfo.allocated_len+=1000;
gpa_hfinfo.hfi=g_realloc(gpa_hfinfo.hfi, sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
case FT_ABSOLUTE_TIME:
g_snprintf(label_str, ITEM_LABEL_LENGTH,
"%s: %s", hfinfo->name,
- abs_time_to_str(fvalue_get(&fi->value), hfinfo->display));
+ abs_time_to_str(fvalue_get(&fi->value), hfinfo->display, TRUE));
break;
case FT_RELATIVE_TIME:
hfinfo->type == FT_INT64)) {
if ((hfinfo->display & BASE_EXT_STRING)) {
- vals = ((value_string_ext *) hfinfo->strings)->vals;
- } if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
+ vals = VALUE_STRING_EXT_VS_P((value_string_ext *) hfinfo->strings);
+ } else if ((hfinfo->display & BASE_RANGE_STRING) == 0) {
vals = hfinfo->strings;
} else {
range = hfinfo->strings;
blurb = hfinfo->blurb;
if (blurb == NULL)
blurb = "";
+ else if (strlen(blurb) == 0)
+ blurb = "\"\"";
if (format == 1) {
printf("F\t%s\t%s\t%s\t%s\t%s\n",
hfinfo->name, hfinfo->abbrev, enum_name,
return format;
}
+static const char *
+hfinfo_numeric_value_format(const header_field_info *hfinfo)
+{
+ const char *format = NULL;
+
+ /* Pick the proper format string */
+ if (hfinfo->type == FT_FRAMENUM) {
+ /*
+ * Frame numbers are always displayed in decimal.
+ */
+ format = "%u";
+ } else {
+ /* Get the underlying BASE_ value */
+ switch(hfinfo->display & BASE_DISPLAY_E_MASK) {
+ case BASE_DEC:
+ case BASE_DEC_HEX:
+ case BASE_OCT: /* I'm lazy */
+ case BASE_CUSTOM:
+ switch(hfinfo->type) {
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ format = "%u";
+ break;
+ case FT_UINT64:
+ format = "%" G_GINT64_MODIFIER "u";
+ break;
+ case FT_INT8:
+ case FT_INT16:
+ case FT_INT24:
+ case FT_INT32:
+ format = "%d";
+ break;
+ case FT_INT64:
+ format = "%" G_GINT64_MODIFIER "d";
+ break;
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ ;
+ }
+ break;
+ case BASE_HEX:
+ case BASE_HEX_DEC:
+ switch(hfinfo->type) {
+ case FT_UINT8:
+ format = "0x%02x";
+ break;
+ case FT_UINT16:
+ format = "0x%04x";
+ break;
+ case FT_UINT24:
+ format = "0x%06x";
+ break;
+ case FT_UINT32:
+ format = "0x%08x";
+ break;
+ case FT_UINT64:
+ format = "0x%016" G_GINT64_MODIFIER "x";
+ break;
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ ;
+ }
+ break;
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ ;
+ }
+ }
+ return format;
+}
+
/* This function indicates whether it's possible to construct a
* "match selected" display filter string for the specified field,
* returns an indication of whether it's possible, and, if it's
char **filter)
{
header_field_info *hfinfo;
- int abbrev_len;
+ int abbrev_len;
char *ptr;
- int buf_len;
+ int buf_len;
const char *format;
- int dfilter_len, i;
+ int dfilter_len, i;
gint start, length, length_remaining;
guint8 c;
gchar is_signed_num = FALSE;
TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
-
+
CREATE_VALUE_STRING(dst,format,ap);
return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);
TRY_TO_FAKE_THIS_ITEM(tree, hf_index, hf_field);
DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
-
+
CREATE_VALUE_STRING(dst,format,ap);
return proto_tree_add_bits_format_value(tree, hf_index, tvb, bit_offset, no_of_bits, &value, dst);