aboutsummaryrefslogtreecommitdiffstats
path: root/print.c
diff options
context:
space:
mode:
authorBill Meier <wmeier@newsguy.com>2013-02-18 00:51:59 +0000
committerBill Meier <wmeier@newsguy.com>2013-02-18 00:51:59 +0000
commite7ff4a79c05f3f3efb6adcf6ead4501f5873cfb2 (patch)
tree6928c67cf77bcb75d5cbb6c99392845ecf88b701 /print.c
parent4e27a8a034451942971bc679cb3dfaae9133cb95 (diff)
Implement proto_tree_write_fields without using ep_strbufs.
- Fixes https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8348: "tshark -T fields can't print the full value of fields where the value, as a text string, is longer than 65535 bytes" - Reduces ep memory allocation & string copies; svn path=/trunk/; revision=47724
Diffstat (limited to 'print.c')
-rw-r--r--print.c82
1 files changed, 64 insertions, 18 deletions
diff --git a/print.c b/print.c
index b41cd51e53..e032bcc72a 100644
--- a/print.c
+++ b/print.c
@@ -82,7 +82,7 @@ struct _output_fields {
gchar aggregator;
GPtrArray* fields;
GHashTable* field_indicies;
- emem_strbuf_t** field_values;
+ GPtrArray** field_values;
gchar quote;
gboolean includes_col_fields;
};
@@ -780,6 +780,12 @@ write_carrays_finale(FILE *fh _U_)
* Find the data source for a specified field, and return a pointer
* to the data in it. Returns NULL if the data is out of bounds.
*/
+/* XXX: What am I missing ?
+ * Why bother searching for fi->ds_tvb for the matching tvb
+ * in the data_source list ?
+ * IOW: Why not just use fi->ds_tvb for the arg to tvb_get_ptr() ?
+ */
+
static const guint8 *
get_field_data(GSList *src_list, field_info *fi)
{
@@ -1354,6 +1360,14 @@ void output_fields_free(output_fields_t* fields)
*/
g_hash_table_destroy(fields->field_indicies);
}
+ if(NULL != fields->field_values) {
+ gsize i;
+ for(i = 0; i < fields->fields->len; ++i) {
+ GPtrArray* fv_p;
+ fv_p = fields->field_values[i];
+ g_ptr_array_free(fv_p, TRUE);
+ }
+ }
if(NULL != fields->fields) {
gsize i;
for(i = 0; i < fields->fields->len; ++i) {
@@ -1537,21 +1551,47 @@ void write_fields_preamble(output_fields_t* fields, FILE *fh)
static void format_field_values(output_fields_t* fields, gpointer field_index, const gchar* value)
{
- if(NULL != value && '\0' != *value) {
- guint actual_index;
- actual_index = GPOINTER_TO_UINT(field_index);
- /* Unwrap change made to disambiguiate zero / null */
- if (fields->field_values[actual_index - 1] == NULL ) {
- fields->field_values[actual_index - 1] = ep_strbuf_new(value);
- } else if (fields->occurrence == 'l' ) {
- /* print only the value of the last occurrence of the field */
- ep_strbuf_printf(fields->field_values[actual_index - 1],"%s",value);
- } else if (fields->occurrence == 'a' ) {
- /* print the value of all accurrences of the field */
- ep_strbuf_append_printf(fields->field_values[actual_index - 1],
- "%c%s",fields->aggregator,value);
+ guint index;
+ GPtrArray* fv_p;
+
+ if (NULL == value || '\0' == *value)
+ return;
+
+ /* Unwrap change made to disambiguiate zero / null */
+ index = GPOINTER_TO_UINT(field_index) - 1;
+
+ if (fields->field_values[index] == NULL) {
+ fields->field_values[index] = g_ptr_array_new();
+ }
+
+ /* Essentially: fieldvalues[index] is an array of (ghar *) with each entry */
+ /* pointing to a string which is (part of) the final output string. */
+
+ fv_p = fields->field_values[index];
+
+ switch (fields->occurrence) {
+ case 'f':
+ /* print the value of only the first occurrence of the field */
+ if (g_ptr_array_len(fv_p) != 0)
+ return;
+ break;
+ case 'l':
+ /* print the value of only the last occurrence of the field */
+ g_ptr_array_set_size(fv_p, 0);
+ break;
+ case 'a':
+ /* print the value of all accurrences of the field */
+ /* If not the first, add the 'aggregator' */
+ if (g_ptr_array_len(fv_p) > 0) {
+ g_ptr_array_add(fv_p, (gpointer)ep_strdup_printf("%c",fields->aggregator));
}
+ break;
+ default:
+ g_assert_not_reached();
+ break;
}
+
+ g_ptr_array_add(fv_p, (gpointer)value);
}
static void proto_tree_get_node_field_values(proto_node *node, gpointer data)
@@ -1569,7 +1609,7 @@ static void proto_tree_get_node_field_values(proto_node *node, gpointer data)
field_index = g_hash_table_lookup(call_data->fields->field_indicies, fi->hfinfo->abbrev);
if(NULL != field_index) {
format_field_values(call_data->fields, field_index,
- get_node_field_value(fi, call_data->edt) /* ep_alloced string */
+ get_node_field_value(fi, call_data->edt) /* static or ep_alloc'd string */
);
}
@@ -1611,8 +1651,8 @@ void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, colum
}
}
- /* Buffer to store values for this packet */
- fields->field_values = ep_alloc_array0(emem_strbuf_t*, fields->fields->len);
+ /* Array buffer to store values for this packet */
+ fields->field_values = ep_alloc_array0(GPtrArray*, fields->fields->len);
proto_tree_children_foreach(edt->tree, proto_tree_get_node_field_values,
&data);
@@ -1634,10 +1674,16 @@ void proto_tree_write_fields(output_fields_t* fields, epan_dissect_t *edt, colum
fputc(fields->separator, fh);
}
if(NULL != fields->field_values[i]) {
+ GPtrArray *fv_p;
+ gsize j;
+ fv_p = fields->field_values[i];
if(fields->quote != '\0') {
fputc(fields->quote, fh);
}
- fputs(fields->field_values[i]->str, fh);
+
+ for (j = 0; j < g_ptr_array_len(fv_p); j++ ) {
+ fputs((gchar *)g_ptr_array_index(fv_p, j), fh);
+ }
if(fields->quote != '\0') {
fputc(fields->quote, fh);
}