![Gilbert Ramirez](/assets/img/avatar_default.png)
Sometimes you have a capture file that has many duplicate frames because of how the capture was made, and its convenient to ignore the duplicates so you can concentrate on the data and not all the TCP warnings. This adds a preference in the "Protocols" section to ignore duplicates. This currently only works while reading a capture file *not* during a live capture.
93 lines
2.8 KiB
C
93 lines
2.8 KiB
C
/* fifo_string_cache.c
|
|
* A string cache, possibly with a bounded size, using FIFO order to control
|
|
* the size.
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
#include <stdio.h>
|
|
#include "fifo_string_cache.h"
|
|
|
|
void
|
|
fifo_string_cache_init(fifo_string_cache_t *fcache, guint max_entries, GDestroyNotify string_free_func)
|
|
{
|
|
fcache->set = g_hash_table_new_full(g_str_hash, g_str_equal, string_free_func, NULL);
|
|
fcache->head = NULL;
|
|
fcache->tail = NULL;
|
|
fcache->max_entries = max_entries;
|
|
}
|
|
|
|
void
|
|
fifo_string_cache_free(fifo_string_cache_t *fcache)
|
|
{
|
|
if (fcache->set != NULL) {
|
|
g_hash_table_destroy(fcache->set);
|
|
fcache->set = NULL;
|
|
}
|
|
if (fcache->head != NULL) {
|
|
g_slist_free(fcache->head);
|
|
fcache->head = NULL;
|
|
fcache->tail = NULL;
|
|
}
|
|
}
|
|
|
|
gboolean
|
|
fifo_string_cache_contains(fifo_string_cache_t *fcache, const gchar *entry)
|
|
{
|
|
return g_hash_table_contains(fcache->set, entry);
|
|
}
|
|
|
|
gboolean
|
|
fifo_string_cache_insert(fifo_string_cache_t *fcache, const gchar *entry)
|
|
{
|
|
GSList *prev_head;
|
|
GSList *new_start_of_tail;
|
|
|
|
// In GLIB 2.40, g_hash_table_insert() returns a bool that gives us what we
|
|
// need (did the entry exist already?). But, if we're not using that
|
|
// version, we need to first check if the entry exists. So we just check
|
|
// the hash all the time, regardless of GLIB version.
|
|
gboolean exists;
|
|
exists = g_hash_table_contains(fcache->set, entry);
|
|
if (exists) {
|
|
return TRUE;
|
|
}
|
|
|
|
// Shall we remove one item?
|
|
if (fcache->max_entries > 0) {
|
|
if (g_hash_table_size(fcache->set) == fcache->max_entries) {
|
|
g_hash_table_remove(fcache->set, fcache->head->data);
|
|
prev_head = fcache->head;
|
|
fcache->head = fcache->head->next;
|
|
g_slist_free_1(prev_head);
|
|
|
|
// If max_entries is 1, the head was also the tail. Reset the tail.
|
|
if (fcache->tail == prev_head) {
|
|
fcache->tail = NULL;
|
|
}
|
|
|
|
// Now the size of the hash table is max_entries
|
|
}
|
|
}
|
|
|
|
g_hash_table_insert(fcache->set, (gpointer) entry, /*value=*/NULL);
|
|
// Do we need to constrain the number of entries?
|
|
if (fcache->max_entries > 0) {
|
|
// Keep track of the new entry at the end of the queue
|
|
new_start_of_tail = g_slist_append(fcache->tail, (gpointer) entry);
|
|
// Set the new tail
|
|
if (fcache->tail == NULL) {
|
|
fcache->tail = new_start_of_tail;
|
|
// This is the first entry, so head is NULL too. Set it.
|
|
fcache->head = new_start_of_tail;
|
|
} else {
|
|
fcache->tail = new_start_of_tail->next;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|