mirror of https://github.com/Gnucash/gnucash
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
2.7 KiB
139 lines
2.7 KiB
/*
|
|
* String management for the Gnumeric Spreadsheet
|
|
*
|
|
* Author:
|
|
* Miguel de Icaza (miguel@kernel.org)
|
|
*/
|
|
#include <config.h>
|
|
#include "gnumeric.h"
|
|
#include "str.h"
|
|
#include "gutils.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#ifndef USE_STRING_POOLS
|
|
#define USE_STRING_POOLS 1
|
|
#endif
|
|
|
|
#if USE_STRING_POOLS
|
|
/* Memory pool for strings. */
|
|
static GnmMemChunk *string_pool;
|
|
#define CHUNK_ALLOC(T,p) ((T*)gnm_mem_chunk_alloc (p))
|
|
#define CHUNK_FREE(p,v) gnm_mem_chunk_free ((p), (v))
|
|
#else
|
|
#define CHUNK_ALLOC(T,c) g_new (T,1)
|
|
#define CHUNK_FREE(p,v) g_free ((v))
|
|
#endif
|
|
|
|
static GHashTable *string_hash_table;
|
|
|
|
static GnmString *
|
|
gnm_string_lookup (char const *s)
|
|
{
|
|
g_return_val_if_fail (s != NULL, NULL);
|
|
return g_hash_table_lookup (string_hash_table, s);
|
|
}
|
|
|
|
GnmString *
|
|
gnm_string_get (char const *s)
|
|
{
|
|
GnmString *string = gnm_string_lookup (s);
|
|
if (string){
|
|
gnm_string_ref (string);
|
|
return string;
|
|
}
|
|
|
|
/* If non-existant, create */
|
|
string = CHUNK_ALLOC (GnmString, string_pool);
|
|
string->ref_count = 1;
|
|
string->str = g_strdup (s);
|
|
|
|
g_hash_table_insert (string_hash_table, string->str, string);
|
|
|
|
return string;
|
|
}
|
|
|
|
/*
|
|
* gnm_string_get_nocopy :
|
|
*
|
|
* Take control of the supplied string.
|
|
* delete it if it is already available.
|
|
*/
|
|
GnmString *
|
|
gnm_string_get_nocopy (char *s)
|
|
{
|
|
GnmString *string = gnm_string_lookup (s);
|
|
if (string) {
|
|
gnm_string_ref (string);
|
|
g_free (s);
|
|
return string;
|
|
}
|
|
|
|
/* If non-existant, create */
|
|
string = CHUNK_ALLOC (GnmString, string_pool);
|
|
string->ref_count = 1;
|
|
string->str = s;
|
|
|
|
g_hash_table_insert (string_hash_table, string->str, string);
|
|
|
|
return string;
|
|
}
|
|
|
|
GnmString *
|
|
gnm_string_ref (GnmString *string)
|
|
{
|
|
g_return_val_if_fail (string != NULL, NULL);
|
|
|
|
string->ref_count++;
|
|
|
|
return string;
|
|
}
|
|
|
|
void
|
|
gnm_string_unref (GnmString *string)
|
|
{
|
|
g_return_if_fail (string != NULL);
|
|
g_return_if_fail (string->ref_count > 0);
|
|
|
|
if (--(string->ref_count) == 0){
|
|
g_hash_table_remove (string_hash_table, string->str);
|
|
g_free (string->str);
|
|
CHUNK_FREE (string_pool, string);
|
|
}
|
|
}
|
|
|
|
void
|
|
gnm_string_init (void)
|
|
{
|
|
string_hash_table = g_hash_table_new (g_str_hash, g_str_equal);
|
|
#if USE_STRING_POOLS
|
|
string_pool =
|
|
gnm_mem_chunk_new ("string pool",
|
|
sizeof (GnmString),
|
|
16 * 1024 - 128);
|
|
#endif
|
|
}
|
|
|
|
#if USE_STRING_POOLS
|
|
static void
|
|
cb_string_pool_leak (gpointer data, gpointer user)
|
|
{
|
|
GnmString *string = data;
|
|
fprintf (stderr, "Leaking string [%s] with ref_count=%d.\n",
|
|
string->str, string->ref_count);
|
|
}
|
|
#endif
|
|
|
|
void
|
|
gnm_string_shutdown (void)
|
|
{
|
|
g_hash_table_destroy (string_hash_table);
|
|
string_hash_table = NULL;
|
|
#if USE_STRING_POOLS
|
|
gnm_mem_chunk_foreach_leak (string_pool, cb_string_pool_leak, NULL);
|
|
gnm_mem_chunk_destroy (string_pool, FALSE);
|
|
string_pool = NULL;
|
|
#endif
|
|
}
|