2005-09-20 23:26:39 +10:00
/** \file intern.c
Library for pooling common strings
*/
# include "config.h"
2006-02-28 23:17:16 +10:00
2005-09-20 23:26:39 +10:00
# include <stdlib.h>
# include <stdio.h>
# include <wchar.h>
2005-09-29 07:02:24 +10:00
# include <unistd.h>
2012-01-23 20:02:15 -08:00
# include <set>
2012-03-03 15:20:30 -08:00
# include <deque>
# include <algorithm>
2005-09-20 23:26:39 +10:00
2006-02-28 23:17:16 +10:00
# include "fallback.h"
2005-09-20 23:26:39 +10:00
# include "util.h"
2006-02-28 23:17:16 +10:00
2006-01-21 00:27:21 +10:00
# include "wutil.h"
2005-09-20 23:26:39 +10:00
# include "common.h"
# include "intern.h"
2012-01-23 20:02:15 -08:00
/** Comparison function for intern'd strings */
2012-03-03 15:20:30 -08:00
class string_table_compare_t {
public :
bool operator ( ) ( const wchar_t * a , const wchar_t * b ) const {
return wcscmp ( a , b ) < 0 ;
}
} ;
2005-09-20 23:26:39 +10:00
2012-03-03 15:20:30 -08:00
/* A sorted deque ends up being a little more memory efficient than a std::set for the intern'd string table */
# define USE_SET 0
# if USE_SET
2012-01-23 20:02:15 -08:00
/** The table of intern'd strings */
2012-03-03 15:20:30 -08:00
typedef std : : set < const wchar_t * , string_table_compare_t > string_table_t ;
# else
/** The table of intern'd strings */
typedef std : : deque < const wchar_t * > string_table_t ;
# endif
static string_table_t string_table ;
2006-11-11 20:54:52 +10:00
2012-01-23 20:02:15 -08:00
/** The lock to provide thread safety for intern'd strings */
static pthread_mutex_t intern_lock = PTHREAD_MUTEX_INITIALIZER ;
2005-09-20 23:26:39 +10:00
2012-01-23 20:02:15 -08:00
static const wchar_t * intern_with_dup ( const wchar_t * in , bool dup )
2005-09-20 23:26:39 +10:00
{
if ( ! in )
2012-01-23 20:02:15 -08:00
return NULL ;
// debug( 0, L"intern %ls", in );
scoped_lock lock ( intern_lock ) ;
const wchar_t * result ;
2012-03-03 15:20:30 -08:00
# if USE_SET
2012-01-23 20:02:15 -08:00
string_table_t : : const_iterator iter = string_table . find ( in ) ;
if ( iter ! = string_table . end ( ) ) {
result = * iter ;
} else {
result = dup ? wcsdup ( in ) : in ;
string_table . insert ( result ) ;
}
2012-03-03 15:20:30 -08:00
# else
string_table_t : : iterator iter = std : : lower_bound ( string_table . begin ( ) , string_table . end ( ) , in , string_table_compare_t ( ) ) ;
if ( iter ! = string_table . end ( ) & & wcscmp ( * iter , in ) = = 0 ) {
result = * iter ;
} else {
result = dup ? wcsdup ( in ) : in ;
string_table . insert ( iter , result ) ;
}
# endif
2012-01-23 20:02:15 -08:00
return result ;
2005-09-20 23:26:39 +10:00
}
2012-01-23 20:02:15 -08:00
const wchar_t * intern ( const wchar_t * in )
2005-09-20 23:26:39 +10:00
{
2012-01-23 20:02:15 -08:00
return intern_with_dup ( in , true ) ;
2005-09-20 23:26:39 +10:00
}
2012-01-23 20:02:15 -08:00
const wchar_t * intern_static ( const wchar_t * in )
{
return intern_with_dup ( in , false ) ;
2005-09-20 23:26:39 +10:00
}