wireshark/epan/fifo_string_cache.c
Gilbert Ramirez d2c9f1824a Add a preference for ignoring duplicate frames
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.
2023-06-09 07:21:08 +00:00

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;
}