summaryrefslogtreecommitdiff
path: root/libsylph/stringtable.c
diff options
context:
space:
mode:
authorSimeon Simeonov2018-02-26 11:23:00 +0100
committerSimeon Simeonov2018-02-26 11:23:00 +0100
commit0b3cbf57875fd692e4ba0b336fefa4bee1ed00dc (patch)
treeaf916a30553c78ce9d4f2d8658656a175c5b6921 /libsylph/stringtable.c
Initial commit for sylpheed 3.7.0
Diffstat (limited to 'libsylph/stringtable.c')
-rw-r--r--libsylph/stringtable.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/libsylph/stringtable.c b/libsylph/stringtable.c
new file mode 100644
index 0000000..dbb1951
--- /dev/null
+++ b/libsylph/stringtable.c
@@ -0,0 +1,163 @@
1/*
2 * LibSylph -- E-Mail client library
3 * Copyright (C) 1999-2005 Hiroyuki Yamamoto
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <glib.h>
21#include <string.h>
22
23#include "stringtable.h"
24#include "utils.h"
25
26/* alfons - hashed string table (I wasn't content with GStringChunk;
27 * can't recall why :-) */
28
29#if 0
30#define XXX_DEBUG \
31 debug_print
32#else
33#define XXX_DEBUG \
34 if (0) debug_print
35#endif
36
37typedef struct StringEntry_ {
38 gint ref_count;
39 gchar *string;
40} StringEntry;
41
42static StringEntry *string_entry_new(const gchar *str)
43{
44 StringEntry *entry;
45
46 entry = g_new0(StringEntry, 1);
47 entry->ref_count = 1;
48 entry->string = g_strdup(str);
49 return entry;
50}
51
52static void string_entry_free(StringEntry *entry)
53{
54 g_return_if_fail(entry != NULL);
55
56 g_free(entry->string);
57 g_free(entry);
58}
59
60StringTable *string_table_new(void)
61{
62 StringTable *strtable;
63
64 strtable = g_new0(StringTable, 1);
65 g_return_val_if_fail(strtable != NULL, NULL);
66 strtable->hash_table = g_hash_table_new(g_str_hash, g_str_equal);
67 g_return_val_if_fail(strtable->hash_table, NULL);
68 return strtable;
69}
70
71gchar *string_table_lookup_string(StringTable *table, const gchar *str)
72{
73 StringEntry *entry;
74
75 entry = g_hash_table_lookup(table->hash_table, str);
76
77 if (entry) {
78 return entry->string;
79 } else {
80 return NULL;
81 }
82}
83
84gchar *string_table_insert_string(StringTable *table, const gchar *str)
85{
86 StringEntry *entry;
87
88 entry = g_hash_table_lookup(table->hash_table, str);
89
90 if (entry) {
91 entry->ref_count++;
92 XXX_DEBUG ("ref++ for %s (%d)\n", entry->string,
93 entry->ref_count);
94 } else {
95 entry = string_entry_new(str);
96 XXX_DEBUG ("inserting %s\n", str);
97 /* insert entry->string instead of str, since it can be
98 * invalid pointer after this. */
99 g_hash_table_insert(table->hash_table, entry->string, entry);
100 }
101
102 return entry->string;
103}
104
105void string_table_free_string(StringTable *table, const gchar *str)
106{
107 StringEntry *entry;
108
109 entry = g_hash_table_lookup(table->hash_table, str);
110
111 if (entry) {
112 entry->ref_count--;
113 if (entry->ref_count <= 0) {
114 XXX_DEBUG ("refcount of string %s dropped to zero\n",
115 entry->string);
116 g_hash_table_remove(table->hash_table, str);
117 string_entry_free(entry);
118 } else {
119 XXX_DEBUG ("ref-- for %s (%d)\n", entry->string,
120 entry->ref_count);
121 }
122 }
123}
124
125static gboolean string_table_remove_for_each_fn(gchar *key, StringEntry *entry,
126 gpointer user_data)
127{
128 g_return_val_if_fail(key != NULL, TRUE);
129 g_return_val_if_fail(entry != NULL, TRUE);
130
131 string_entry_free(entry);
132
133 return TRUE;
134}
135
136void string_table_free(StringTable *table)
137{
138 g_return_if_fail(table != NULL);
139 g_return_if_fail(table->hash_table != NULL);
140
141 g_hash_table_foreach_remove(table->hash_table,
142 (GHRFunc)string_table_remove_for_each_fn,
143 NULL);
144 g_hash_table_destroy(table->hash_table);
145 g_free(table);
146}
147
148static void string_table_stats_for_each_fn(gchar *key, StringEntry *entry,
149 guint *totals)
150{
151 if (entry->ref_count > 1) {
152 *totals += strlen(key) * (entry->ref_count - 1);
153 }
154}
155
156void string_table_get_stats(StringTable *table)
157{
158 guint totals = 0;
159
160 g_hash_table_foreach(table->hash_table,
161 (GHFunc)string_table_stats_for_each_fn, &totals);
162 XXX_DEBUG ("TOTAL UNSPILLED %d (%dK)\n", totals, totals / 1024);
163}