From f36577b27b6f352f140cf1f25755d39661bd4072 Mon Sep 17 00:00:00 2001 From: hiro Date: Wed, 31 Aug 2005 06:10:31 +0000 Subject: made some core modules library (libsylph). git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@528 ee746299-78ed-0310-b773-934348b2243d --- libsylph/stringtable.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 libsylph/stringtable.c (limited to 'libsylph/stringtable.c') diff --git a/libsylph/stringtable.c b/libsylph/stringtable.c new file mode 100644 index 00000000..da5e0ea4 --- /dev/null +++ b/libsylph/stringtable.c @@ -0,0 +1,163 @@ +/* + * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client + * Copyright (C) 1999-2001 Hiroyuki Yamamoto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include "stringtable.h" +#include "utils.h" + +/* alfons - hashed string table (I wasn't content with GStringChunk; + * can't recall why :-) */ + +#if 0 +#define XXX_DEBUG \ + debug_print +#else +#define XXX_DEBUG \ + if (0) debug_print +#endif + +typedef struct StringEntry_ { + gint ref_count; + gchar *string; +} StringEntry; + +static StringEntry *string_entry_new(const gchar *str) +{ + StringEntry *entry; + + entry = g_new0(StringEntry, 1); + entry->ref_count = 1; + entry->string = g_strdup(str); + return entry; +} + +static void string_entry_free(StringEntry *entry) +{ + g_return_if_fail(entry != NULL); + + g_free(entry->string); + g_free(entry); +} + +StringTable *string_table_new(void) +{ + StringTable *strtable; + + strtable = g_new0(StringTable, 1); + g_return_val_if_fail(strtable != NULL, NULL); + strtable->hash_table = g_hash_table_new(g_str_hash, g_str_equal); + g_return_val_if_fail(strtable->hash_table, NULL); + return strtable; +} + +gchar *string_table_lookup_string(StringTable *table, const gchar *str) +{ + StringEntry *entry; + + entry = g_hash_table_lookup(table->hash_table, str); + + if (entry) { + return entry->string; + } else { + return NULL; + } +} + +gchar *string_table_insert_string(StringTable *table, const gchar *str) +{ + StringEntry *entry; + + entry = g_hash_table_lookup(table->hash_table, str); + + if (entry) { + entry->ref_count++; + XXX_DEBUG ("ref++ for %s (%d)\n", entry->string, + entry->ref_count); + } else { + entry = string_entry_new(str); + XXX_DEBUG ("inserting %s\n", str); + /* insert entry->string instead of str, since it can be + * invalid pointer after this. */ + g_hash_table_insert(table->hash_table, entry->string, entry); + } + + return entry->string; +} + +void string_table_free_string(StringTable *table, const gchar *str) +{ + StringEntry *entry; + + entry = g_hash_table_lookup(table->hash_table, str); + + if (entry) { + entry->ref_count--; + if (entry->ref_count <= 0) { + XXX_DEBUG ("refcount of string %s dropped to zero\n", + entry->string); + g_hash_table_remove(table->hash_table, str); + string_entry_free(entry); + } else { + XXX_DEBUG ("ref-- for %s (%d)\n", entry->string, + entry->ref_count); + } + } +} + +static gboolean string_table_remove_for_each_fn(gchar *key, StringEntry *entry, + gpointer user_data) +{ + g_return_val_if_fail(key != NULL, TRUE); + g_return_val_if_fail(entry != NULL, TRUE); + + string_entry_free(entry); + + return TRUE; +} + +void string_table_free(StringTable *table) +{ + g_return_if_fail(table != NULL); + g_return_if_fail(table->hash_table != NULL); + + g_hash_table_foreach_remove(table->hash_table, + (GHRFunc)string_table_remove_for_each_fn, + NULL); + g_hash_table_destroy(table->hash_table); + g_free(table); +} + +static void string_table_stats_for_each_fn(gchar *key, StringEntry *entry, + guint *totals) +{ + if (entry->ref_count > 1) { + *totals += strlen(key) * (entry->ref_count - 1); + } +} + +void string_table_get_stats(StringTable *table) +{ + guint totals = 0; + + g_hash_table_foreach(table->hash_table, + (GHFunc)string_table_stats_for_each_fn, &totals); + XXX_DEBUG ("TOTAL UNSPILLED %d (%dK)\n", totals, totals / 1024); +} -- cgit v1.2.3