forked from osmocom/wireshark
Replace linked list of proto fields with array
This is substantially more memory-efficient, shaving another ~1.5MB off our base usage. It also lets us remove the annoying extra "last_field" pointer and simplify proto_register_field_common(). It also accidentally fixed what may have been a memory leak in proto_unregister_field(). It unfortunately complicates proto_get_next_protocol_field() to require refetching the protocol each time, but that is itself just an array-lookup under the covers (and isn't much used), so I don't expect the performance hit to be noticable. Change-Id: I8e1006b2326d6563fc3b710b827cc99b54440df1 Reviewed-on: https://code.wireshark.org/review/1225 Reviewed-by: Michael Mann <mmann78@netscape.net> Reviewed-by: Evan Huus <eapache@gmail.com>
This commit is contained in:
parent
5983cda769
commit
d47ae54806
51
epan/proto.c
51
epan/proto.c
|
@ -280,8 +280,7 @@ struct _protocol {
|
||||||
const char *name; /* long description */
|
const char *name; /* long description */
|
||||||
const char *short_name; /* short description */
|
const char *short_name; /* short description */
|
||||||
const char *filter_name; /* name of this protocol in filters */
|
const char *filter_name; /* name of this protocol in filters */
|
||||||
GSList *fields; /* fields for this protocol */
|
GPtrArray *fields; /* fields for this protocol */
|
||||||
GSList *last_field; /* pointer to end of list of fields */
|
|
||||||
int proto_id; /* field ID for this protocol */
|
int proto_id; /* field ID for this protocol */
|
||||||
gboolean is_enabled; /* TRUE if protocol is enabled */
|
gboolean is_enabled; /* TRUE if protocol is enabled */
|
||||||
gboolean can_toggle; /* TRUE if is_enabled can be changed */
|
gboolean can_toggle; /* TRUE if is_enabled can be changed */
|
||||||
|
@ -534,7 +533,7 @@ proto_cleanup(void)
|
||||||
DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
|
DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
|
||||||
|
|
||||||
g_slice_free(header_field_info, hfinfo);
|
g_slice_free(header_field_info, hfinfo);
|
||||||
g_slist_free(protocol->fields);
|
g_ptr_array_free(protocol->fields, TRUE);
|
||||||
protocols = g_list_remove(protocols, protocol);
|
protocols = g_list_remove(protocols, protocol);
|
||||||
g_free(protocol);
|
g_free(protocol);
|
||||||
}
|
}
|
||||||
|
@ -4825,7 +4824,7 @@ proto_register_protocol(const char *name, const char *short_name,
|
||||||
protocol->name = name;
|
protocol->name = name;
|
||||||
protocol->short_name = short_name;
|
protocol->short_name = short_name;
|
||||||
protocol->filter_name = filter_name;
|
protocol->filter_name = filter_name;
|
||||||
protocol->fields = NULL;
|
protocol->fields = g_ptr_array_new();
|
||||||
protocol->is_enabled = TRUE; /* protocol is enabled by default */
|
protocol->is_enabled = TRUE; /* protocol is enabled by default */
|
||||||
protocol->can_toggle = TRUE;
|
protocol->can_toggle = TRUE;
|
||||||
protocol->is_private = FALSE;
|
protocol->is_private = FALSE;
|
||||||
|
@ -4913,26 +4912,28 @@ proto_get_next_protocol(void **cookie)
|
||||||
header_field_info *
|
header_field_info *
|
||||||
proto_get_first_protocol_field(const int proto_id, void **cookie)
|
proto_get_first_protocol_field(const int proto_id, void **cookie)
|
||||||
{
|
{
|
||||||
protocol_t *protocol = find_protocol_by_id(proto_id);
|
protocol_t *protocol = find_protocol_by_id(proto_id);
|
||||||
|
|
||||||
if ((protocol == NULL) || (protocol->fields == NULL))
|
if ((protocol == NULL) || (protocol->fields->len == 0))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*cookie = protocol->fields;
|
*cookie = GINT_TO_POINTER(0);
|
||||||
return (header_field_info *)protocol->fields->data;
|
return (header_field_info *)g_ptr_array_index(protocol->fields, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
header_field_info *
|
header_field_info *
|
||||||
proto_get_next_protocol_field(void **cookie)
|
proto_get_next_protocol_field(const int proto_id, void **cookie)
|
||||||
{
|
{
|
||||||
GSList *list_item = (GSList *)*cookie;
|
protocol_t *protocol = find_protocol_by_id(proto_id);
|
||||||
|
guint index = GPOINTER_TO_INT(*cookie);
|
||||||
|
|
||||||
list_item = g_slist_next(list_item);
|
index++;
|
||||||
if (list_item == NULL)
|
|
||||||
|
if (index >= protocol->fields->len)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*cookie = list_item;
|
*cookie = GINT_TO_POINTER(index);
|
||||||
return (header_field_info *)list_item->data;
|
return (header_field_info *)g_ptr_array_index(protocol->fields, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol_t *
|
protocol_t *
|
||||||
|
@ -5096,13 +5097,7 @@ static int
|
||||||
proto_register_field_common(protocol_t *proto, header_field_info *hfi, const int parent)
|
proto_register_field_common(protocol_t *proto, header_field_info *hfi, const int parent)
|
||||||
{
|
{
|
||||||
if (proto != NULL) {
|
if (proto != NULL) {
|
||||||
if (proto->fields == NULL) {
|
g_ptr_array_add(proto->fields, hfi);
|
||||||
proto->fields = g_slist_append(NULL, hfi);
|
|
||||||
proto->last_field = proto->fields;
|
|
||||||
} else {
|
|
||||||
proto->last_field =
|
|
||||||
g_slist_append(proto->last_field, hfi)->next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return proto_register_field_init(hfi, parent);
|
return proto_register_field_init(hfi, parent);
|
||||||
|
@ -5188,25 +5183,23 @@ proto_unregister_field (const int parent, gint hf_id)
|
||||||
{
|
{
|
||||||
hf_register_info *hf;
|
hf_register_info *hf;
|
||||||
protocol_t *proto;
|
protocol_t *proto;
|
||||||
GSList *field;
|
guint i;
|
||||||
|
|
||||||
if (hf_id == -1 || hf_id == 0)
|
if (hf_id == -1 || hf_id == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
proto = find_protocol_by_id (parent);
|
proto = find_protocol_by_id (parent);
|
||||||
if (!proto || !proto->fields) {
|
if (!proto || proto->fields->len == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (field = proto->fields; field; field = field->next) {
|
for (i = 0; i < proto->fields->len; i++) {
|
||||||
hf = (hf_register_info *)field->data;
|
hf = (hf_register_info *)g_ptr_array_index(proto->fields, i);
|
||||||
if (*hf->p_id == hf_id) {
|
if (*hf->p_id == hf_id) {
|
||||||
/* Found the hf_id in this protocol */
|
/* Found the hf_id in this protocol */
|
||||||
g_hash_table_steal(gpa_name_map, hf->hfinfo.abbrev);
|
g_hash_table_steal(gpa_name_map, hf->hfinfo.abbrev);
|
||||||
/* XXX, memleak? g_slist_delete_link() */
|
g_ptr_array_remove_index_fast(proto->fields, i);
|
||||||
proto->fields = g_slist_remove_link (proto->fields, field);
|
return;
|
||||||
proto->last_field = g_slist_last (proto->fields);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1900,8 +1900,8 @@ extern gint proto_registrar_get_length(const int n);
|
||||||
WS_DLL_PUBLIC int proto_get_first_protocol(void **cookie);
|
WS_DLL_PUBLIC int proto_get_first_protocol(void **cookie);
|
||||||
WS_DLL_PUBLIC int proto_get_data_protocol(void *cookie);
|
WS_DLL_PUBLIC int proto_get_data_protocol(void *cookie);
|
||||||
WS_DLL_PUBLIC int proto_get_next_protocol(void **cookie);
|
WS_DLL_PUBLIC int proto_get_next_protocol(void **cookie);
|
||||||
WS_DLL_PUBLIC header_field_info *proto_get_first_protocol_field(const int proto_id, void **cookle);
|
WS_DLL_PUBLIC header_field_info *proto_get_first_protocol_field(const int proto_id, void **cookie);
|
||||||
WS_DLL_PUBLIC header_field_info *proto_get_next_protocol_field(void **cookle);
|
WS_DLL_PUBLIC header_field_info *proto_get_next_protocol_field(const int proto_id, void **cookie);
|
||||||
|
|
||||||
/** Given a protocol's filter_name.
|
/** Given a protocol's filter_name.
|
||||||
@param filter_name the filter name to search for
|
@param filter_name the filter name to search for
|
||||||
|
|
|
@ -538,7 +538,7 @@ WSLUA_CONSTRUCTOR Field_list(lua_State *L) {
|
||||||
i = proto_get_next_protocol(&cookie)) {
|
i = proto_get_next_protocol(&cookie)) {
|
||||||
|
|
||||||
for (hfinfo = proto_get_first_protocol_field(i, &cookie2); hfinfo != NULL;
|
for (hfinfo = proto_get_first_protocol_field(i, &cookie2); hfinfo != NULL;
|
||||||
hfinfo = proto_get_next_protocol_field(&cookie2)) {
|
hfinfo = proto_get_next_protocol_field(i, &cookie2)) {
|
||||||
|
|
||||||
if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
|
if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -657,7 +657,7 @@ build_autocompletion_list(GtkWidget *filter_te, GtkWidget *treeview, GtkWidget *
|
||||||
|
|
||||||
for (hfinfo = proto_get_first_protocol_field(i, &cookie2);
|
for (hfinfo = proto_get_first_protocol_field(i, &cookie2);
|
||||||
hfinfo != NULL;
|
hfinfo != NULL;
|
||||||
hfinfo = proto_get_next_protocol_field(&cookie2))
|
hfinfo = proto_get_next_protocol_field(i, &cookie2))
|
||||||
{
|
{
|
||||||
if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
|
if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -98,7 +98,7 @@ proto_hier_tree_iter_nth_child(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkT
|
||||||
break;
|
break;
|
||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
hfinfo = proto_get_next_protocol_field(&cookie);
|
hfinfo = proto_get_next_protocol_field(proto_id, &cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* not found? */
|
/* not found? */
|
||||||
|
@ -238,13 +238,14 @@ proto_hier_tree_iter_next(GtkTreeModel *tree_model, GtkTreeIter *iter)
|
||||||
{
|
{
|
||||||
void *cookie2 = iter->user_data2;
|
void *cookie2 = iter->user_data2;
|
||||||
header_field_info *hfinfo;
|
header_field_info *hfinfo;
|
||||||
|
int proto_id = proto_get_data_protocol(iter->user_data);
|
||||||
|
|
||||||
hfinfo = proto_get_next_protocol_field(&cookie2);
|
hfinfo = proto_get_next_protocol_field(proto_id, &cookie2);
|
||||||
/* get next field */
|
/* get next field */
|
||||||
while (hfinfo) {
|
while (hfinfo) {
|
||||||
if (hfinfo->same_name_prev_id == -1)
|
if (hfinfo->same_name_prev_id == -1)
|
||||||
break;
|
break;
|
||||||
hfinfo = proto_get_next_protocol_field(&cookie2);
|
hfinfo = proto_get_next_protocol_field(proto_id, &cookie2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* not found? */
|
/* not found? */
|
||||||
|
@ -289,7 +290,7 @@ proto_hier_tree_iter_n_children(GtkTreeModel *tree_model, GtkTreeIter *iter)
|
||||||
p_id = proto_get_data_protocol(iter->user_data);
|
p_id = proto_get_data_protocol(iter->user_data);
|
||||||
|
|
||||||
/* count not-duplicated fields */
|
/* count not-duplicated fields */
|
||||||
for (hfinfo = proto_get_first_protocol_field(p_id, &cookie); hfinfo; hfinfo = proto_get_next_protocol_field(&cookie)) {
|
for (hfinfo = proto_get_first_protocol_field(p_id, &cookie); hfinfo; hfinfo = proto_get_next_protocol_field(p_id, &cookie)) {
|
||||||
if (hfinfo->same_name_prev_id != -1)
|
if (hfinfo->same_name_prev_id != -1)
|
||||||
continue;
|
continue;
|
||||||
count++;
|
count++;
|
||||||
|
@ -350,7 +351,7 @@ proto_hier_tree_get_path(GtkTreeModel *tree_model, GtkTreeIter *iter)
|
||||||
header_field_info *hfinfo;
|
header_field_info *hfinfo;
|
||||||
|
|
||||||
pos = 0;
|
pos = 0;
|
||||||
for (hfinfo = proto_get_first_protocol_field(p_id, &cookie); hfinfo && hfinfo != iter->user_data3; hfinfo = proto_get_next_protocol_field(&cookie)) {
|
for (hfinfo = proto_get_first_protocol_field(p_id, &cookie); hfinfo && hfinfo != iter->user_data3; hfinfo = proto_get_next_protocol_field(p_id, &cookie)) {
|
||||||
if (hfinfo->same_name_prev_id != -1)
|
if (hfinfo->same_name_prev_id != -1)
|
||||||
continue;
|
continue;
|
||||||
pos++;
|
pos++;
|
||||||
|
|
|
@ -255,7 +255,7 @@ static void set_supported_text(GtkWidget *w, supported_type_t type)
|
||||||
i = proto_get_next_protocol(&cookie)) {
|
i = proto_get_next_protocol(&cookie)) {
|
||||||
|
|
||||||
for (hfinfo = proto_get_first_protocol_field(i, &cookie2); hfinfo != NULL;
|
for (hfinfo = proto_get_first_protocol_field(i, &cookie2); hfinfo != NULL;
|
||||||
hfinfo = proto_get_next_protocol_field(&cookie2)) {
|
hfinfo = proto_get_next_protocol_field(i, &cookie2)) {
|
||||||
|
|
||||||
if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
|
if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
|
||||||
continue;
|
continue;
|
||||||
|
@ -283,7 +283,7 @@ static void set_supported_text(GtkWidget *w, supported_type_t type)
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
for (hfinfo = proto_get_first_protocol_field(i, &cookie2); hfinfo != NULL;
|
for (hfinfo = proto_get_first_protocol_field(i, &cookie2); hfinfo != NULL;
|
||||||
hfinfo = proto_get_next_protocol_field(&cookie2)) {
|
hfinfo = proto_get_next_protocol_field(i, &cookie2)) {
|
||||||
|
|
||||||
if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
|
if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
|
||||||
continue;
|
continue;
|
||||||
|
@ -296,7 +296,7 @@ static void set_supported_text(GtkWidget *w, supported_type_t type)
|
||||||
insert_text(w, buffer, len);
|
insert_text(w, buffer, len);
|
||||||
|
|
||||||
for (hfinfo = proto_get_first_protocol_field(i, &cookie2); hfinfo != NULL;
|
for (hfinfo = proto_get_first_protocol_field(i, &cookie2); hfinfo != NULL;
|
||||||
hfinfo = proto_get_next_protocol_field(&cookie2)) {
|
hfinfo = proto_get_next_protocol_field(i, &cookie2)) {
|
||||||
|
|
||||||
if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
|
if (hfinfo->same_name_prev_id != -1) /* ignore duplicate names */
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in New Issue