aboutsummaryrefslogtreecommitdiffhomepage
path: root/intern.c
diff options
context:
space:
mode:
Diffstat (limited to 'intern.c')
-rw-r--r--intern.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/intern.c b/intern.c
new file mode 100644
index 00000000..2c7d2eff
--- /dev/null
+++ b/intern.c
@@ -0,0 +1,119 @@
+/** \file intern.c
+
+ Library for pooling common strings
+
+*/
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <wchar.h>
+
+#include "util.h"
+#include "common.h"
+#include "intern.h"
+
+hash_table_t *intern_table=0;
+hash_table_t *intern_static_table=0;
+
+static void intern_load_common_static()
+{
+ intern_static( L"" );
+}
+
+const wchar_t *intern( const wchar_t *in )
+{
+ const wchar_t *res=0;
+
+ if( !in )
+ return 0;
+
+ intern_load_common_static();
+
+
+ if( !intern_table )
+ {
+ intern_table = malloc( sizeof( hash_table_t ) );
+ if( !intern_table )
+ {
+ die_mem();
+ }
+ hash_init( intern_table, &hash_wcs_func, &hash_wcs_cmp );
+ }
+
+ if( intern_static_table )
+ {
+ res = hash_get( intern_static_table, in );
+ }
+
+ if( !res )
+ {
+ res = hash_get( intern_table, in );
+
+ if( !res )
+ {
+ res = wcsdup( in );
+ if( !res )
+ {
+ die_mem();
+ }
+
+ hash_put( intern_table, res, res );
+ }
+ }
+
+ return res;
+}
+
+const wchar_t *intern_static( const wchar_t *in )
+{
+ const wchar_t *res=0;
+
+ if( !in )
+ return 0;
+
+ if( !intern_static_table )
+ {
+ intern_static_table = malloc( sizeof( hash_table_t ) );
+ if( !intern_static_table )
+ {
+ die_mem();
+ }
+ hash_init( intern_static_table, &hash_wcs_func, &hash_wcs_cmp );
+ }
+
+ res = hash_get( intern_static_table, in );
+
+ if( !res )
+ {
+ res = in;
+ hash_put( intern_static_table, res, res );
+ }
+
+ return res;
+}
+
+static void clear_value( const void *key, const void *data )
+{
+ debug( 3, L"interned string: '%ls'", data );
+ free( (void *)data );
+}
+
+void intern_free_all()
+{
+ if( intern_table )
+ {
+ hash_foreach( intern_table, &clear_value );
+ hash_destroy( intern_table );
+ free( intern_table );
+ intern_table=0;
+ }
+
+ if( intern_static_table )
+ {
+ hash_destroy( intern_static_table );
+ free( intern_static_table );
+ intern_static_table=0;
+ }
+
+}