SStrHash: Difference between revisions

From wowdev
Jump to navigation Jump to search
(Created page with "This function closely resembles the hashing used in MPQ files, but uses a way smaller table and index into that table. It is usually used with uppercase-backslash strings...")
 
mNo edit summary
 
Line 23: Line 23:
   uint32_t shift = 0xEEEEEEEE;
   uint32_t shift = 0xEEEEEEEE;
   while (*string) {
   while (*string) {
     char const c = no_caseconv ? (*string++) : upper_backslash (*string++);
     char c = *string++;
    if (!no_caseconv) {
      c = upper_backslash (c);
    }
   
   
     seed = (s_hashtable[c >> 4] - s_hashtable[c & 0xF]) ^ (shift + seed);
     seed = (s_hashtable[c >> 4] - s_hashtable[c & 0xF]) ^ (shift + seed);

Latest revision as of 18:56, 19 April 2020

This function closely resembles the hashing used in MPQ files, but uses a way smaller table and index into that table. It is usually used with uppercase-backslash strings and does by default convert to upper before hashing.

Source of the hash table and seed/shift constants are unknown. Other MPQ related hashing uses a generated table, but this one is hardcoded in Storm.

This function is used in various hash tables in the client, as well as Chat "Translation" and DB2 Table Hashes.

static char upper_backslash (char c) {
  return c == '/' ? '\\' : toupper (c);
}
static uint32_t const s_hashtable[16] = {
  0x486E26EE, 0xDCAA16B3, 0xE1918EEF, 0x202DAFDB,
  0x341C7DC7, 0x1C365303, 0x40EF2D37, 0x65FD5E49,
  0xD6057177, 0x904ECE93, 0x1C38024F, 0x98FD323B,
  0xE3061AE7, 0xA39B0FA1, 0x9797F25F, 0xE4444563,
};
uint32_t SStrHash (char const* string, bool no_caseconv, uint32_t seed)
{
  assert (string);
  if (!seed) {
    seed = 0x7FED7FED;
  }

  uint32_t shift = 0xEEEEEEEE;
  while (*string) {
    char c = *string++;
    if (!no_caseconv) {
      c = upper_backslash (c);
    }

    seed = (s_hashtable[c >> 4] - s_hashtable[c & 0xF]) ^ (shift + seed);
    shift = c + seed + 33 * shift + 3;
  }

  return seed ? seed : 1;
}