Commit 2c526b7f authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

msi: Replace the string table hash with a sorted index.

parent ef522c5e
...@@ -40,12 +40,10 @@ ...@@ -40,12 +40,10 @@
WINE_DEFAULT_DEBUG_CHANNEL(msidb); WINE_DEFAULT_DEBUG_CHANNEL(msidb);
#define HASH_SIZE 0x101
#define LONG_STR_BYTES 3 #define LONG_STR_BYTES 3
typedef struct _msistring typedef struct _msistring
{ {
int hash_next;
UINT persistent_refcount; UINT persistent_refcount;
UINT nonpersistent_refcount; UINT nonpersistent_refcount;
LPWSTR str; LPWSTR str;
...@@ -56,30 +54,15 @@ struct string_table ...@@ -56,30 +54,15 @@ struct string_table
UINT maxcount; /* the number of strings */ UINT maxcount; /* the number of strings */
UINT freeslot; UINT freeslot;
UINT codepage; UINT codepage;
int hash[HASH_SIZE]; UINT sortcount;
msistring *strings; /* an array of strings (in the tree) */ BOOL valid_index;
msistring *strings; /* an array of strings */
UINT *sorted; /* index */
}; };
static UINT msistring_makehash( const WCHAR *str )
{
UINT hash = 0;
if (str==NULL)
return hash;
while( *str )
{
hash ^= *str++;
hash *= 53;
hash = (hash<<5) | (hash>>27);
}
return hash % HASH_SIZE;
}
static string_table *init_stringtable( int entries, UINT codepage ) static string_table *init_stringtable( int entries, UINT codepage )
{ {
string_table *st; string_table *st;
int i;
if (codepage != CP_ACP && !IsValidCodePage(codepage)) if (codepage != CP_ACP && !IsValidCodePage(codepage))
{ {
...@@ -92,18 +75,26 @@ static string_table *init_stringtable( int entries, UINT codepage ) ...@@ -92,18 +75,26 @@ static string_table *init_stringtable( int entries, UINT codepage )
return NULL; return NULL;
if( entries < 1 ) if( entries < 1 )
entries = 1; entries = 1;
st->strings = msi_alloc_zero( sizeof (msistring) * entries ); st->strings = msi_alloc_zero( sizeof (msistring) * entries );
if( !st->strings ) if( !st->strings )
{ {
msi_free( st ); msi_free( st );
return NULL; return NULL;
} }
st->sorted = msi_alloc( sizeof (UINT) * entries );
if( !st->sorted )
{
msi_free( st->strings );
msi_free( st );
return NULL;
}
st->maxcount = entries; st->maxcount = entries;
st->freeslot = 1; st->freeslot = 1;
st->codepage = codepage; st->codepage = codepage;
st->sortcount = 0;
for( i=0; i<HASH_SIZE; i++ )
st->hash[i] = -1;
return st; return st;
} }
...@@ -119,12 +110,13 @@ VOID msi_destroy_stringtable( string_table *st ) ...@@ -119,12 +110,13 @@ VOID msi_destroy_stringtable( string_table *st )
msi_free( st->strings[i].str ); msi_free( st->strings[i].str );
} }
msi_free( st->strings ); msi_free( st->strings );
msi_free( st->sorted );
msi_free( st ); msi_free( st );
} }
static int st_find_free_entry( string_table *st ) static int st_find_free_entry( string_table *st )
{ {
UINT i, sz; UINT i, sz, *s;
msistring *p; msistring *p;
TRACE("%p\n", st); TRACE("%p\n", st);
...@@ -146,7 +138,17 @@ static int st_find_free_entry( string_table *st ) ...@@ -146,7 +138,17 @@ static int st_find_free_entry( string_table *st )
p = msi_realloc_zero( st->strings, sz*sizeof(msistring) ); p = msi_realloc_zero( st->strings, sz*sizeof(msistring) );
if( !p ) if( !p )
return -1; return -1;
s = msi_realloc( st->sorted, sz*sizeof(UINT) );
if( !s )
{
msi_free( p );
return -1;
}
st->strings = p; st->strings = p;
st->sorted = s;
st->freeslot = st->maxcount; st->freeslot = st->maxcount;
st->maxcount = sz; st->maxcount = sz;
if( st->strings[st->freeslot].persistent_refcount || if( st->strings[st->freeslot].persistent_refcount ||
...@@ -155,10 +157,40 @@ static int st_find_free_entry( string_table *st ) ...@@ -155,10 +157,40 @@ static int st_find_free_entry( string_table *st )
return st->freeslot; return st->freeslot;
} }
static void set_st_entry( string_table *st, UINT n, LPWSTR str, UINT refcount, enum StringPersistence persistence ) static int find_insert_index( const string_table *st, UINT string_id )
{ {
UINT hash = msistring_makehash( str ); int i, c, low = 0, high = st->sortcount - 1;
while (low <= high)
{
i = (low + high) / 2;
c = lstrcmpW( st->strings[string_id].str, st->strings[st->sorted[i]].str );
if (c < 0)
high = i - 1;
else if (c > 0)
low = i + 1;
else
return -1; /* already exists */
}
return high + 1;
}
static void insert_string_sorted( string_table *st, UINT string_id )
{
int i;
i = find_insert_index( st, string_id );
if (i == -1)
return;
memmove( &st->sorted[i] + 1, &st->sorted[i], (st->sortcount - i) * sizeof(UINT) );
st->sorted[i] = string_id;
st->sortcount++;
}
static void set_st_entry( string_table *st, UINT n, LPWSTR str, UINT refcount, enum StringPersistence persistence )
{
if (persistence == StringPersistent) if (persistence == StringPersistent)
{ {
st->strings[n].persistent_refcount = refcount; st->strings[n].persistent_refcount = refcount;
...@@ -172,8 +204,7 @@ static void set_st_entry( string_table *st, UINT n, LPWSTR str, UINT refcount, e ...@@ -172,8 +204,7 @@ static void set_st_entry( string_table *st, UINT n, LPWSTR str, UINT refcount, e
st->strings[n].str = str; st->strings[n].str = str;
st->strings[n].hash_next = st->hash[hash]; insert_string_sorted( st, n );
st->hash[hash] = n;
if( n < st->maxcount ) if( n < st->maxcount )
st->freeslot = n + 1; st->freeslot = n + 1;
...@@ -382,14 +413,20 @@ static UINT msi_id2stringA( const string_table *st, UINT id, LPSTR buffer, UINT ...@@ -382,14 +413,20 @@ static UINT msi_id2stringA( const string_table *st, UINT id, LPSTR buffer, UINT
*/ */
UINT msi_string2idW( const string_table *st, LPCWSTR str, UINT *id ) UINT msi_string2idW( const string_table *st, LPCWSTR str, UINT *id )
{ {
UINT n, hash = msistring_makehash( str ); int i, c, low = 0, high = st->sortcount - 1;
msistring *se = st->strings;
for (n = st->hash[hash]; n != -1; n = st->strings[n].hash_next ) while (low <= high)
{ {
if ((str == se[n].str) || !lstrcmpW(str, se[n].str)) i = (low + high) / 2;
c = lstrcmpW( str, st->strings[st->sorted[i]].str );
if (c < 0)
high = i - 1;
else if (c > 0)
low = i + 1;
else
{ {
*id = n; *id = st->sorted[i];
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment