2 * A string cache, possibly with a bounded size, using FIFO order to control
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "fifo_string_cache.h"
15 fifo_string_cache_init(fifo_string_cache_t
*fcache
, unsigned max_entries
, GDestroyNotify string_free_func
)
17 fcache
->set
= g_hash_table_new_full(g_str_hash
, g_str_equal
, string_free_func
, NULL
);
20 fcache
->max_entries
= max_entries
;
24 fifo_string_cache_free(fifo_string_cache_t
*fcache
)
26 if (fcache
->set
!= NULL
) {
27 g_hash_table_destroy(fcache
->set
);
30 if (fcache
->head
!= NULL
) {
31 g_slist_free(fcache
->head
);
38 fifo_string_cache_contains(fifo_string_cache_t
*fcache
, const char *entry
)
40 return g_hash_table_contains(fcache
->set
, entry
);
44 fifo_string_cache_insert(fifo_string_cache_t
*fcache
, const char *entry
)
47 GSList
*new_start_of_tail
;
49 // In GLIB 2.40, g_hash_table_insert() returns a bool that gives us what we
50 // need (did the entry exist already?). But, if we're not using that
51 // version, we need to first check if the entry exists. So we just check
52 // the hash all the time, regardless of GLIB version.
54 exists
= g_hash_table_contains(fcache
->set
, entry
);
59 // Shall we remove one item?
60 if (fcache
->max_entries
> 0) {
61 if (g_hash_table_size(fcache
->set
) == fcache
->max_entries
) {
62 g_hash_table_remove(fcache
->set
, fcache
->head
->data
);
63 prev_head
= fcache
->head
;
64 fcache
->head
= fcache
->head
->next
;
65 g_slist_free_1(prev_head
);
67 // If max_entries is 1, the head was also the tail. Reset the tail.
68 if (fcache
->tail
== prev_head
) {
72 // Now the size of the hash table is max_entries
76 g_hash_table_insert(fcache
->set
, (void *) entry
, /*value=*/NULL
);
77 // Do we need to constrain the number of entries?
78 if (fcache
->max_entries
> 0) {
79 // Keep track of the new entry at the end of the queue
80 new_start_of_tail
= g_slist_append(fcache
->tail
, (void *) entry
);
82 if (fcache
->tail
== NULL
) {
83 fcache
->tail
= new_start_of_tail
;
84 // This is the first entry, so head is NULL too. Set it.
85 fcache
->head
= new_start_of_tail
;
87 fcache
->tail
= new_start_of_tail
->next
;