forked from osmocom/wireshark
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
This commit is contained in:
parent
4e27a8a034
commit
e7ff4a79c0
84
print.c
84
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue