FreeBSD/contrib/subversion/subversion/libsvn_subr/hash.c
/* apr_hashfunc_t optimized for the key that we use in SVN: paths and
 * property names.  Its primary goal is speed for keys of known length.
 *
 * Since strings tend to spawn large value spaces (usually differ in many
 * bits with differences spanning a larger section of the key), we can be
 * quite sloppy extracting a hash value.  The more keys there are in a
 * hash container, the more bits of the value returned by this function
 * will be used.  For a small number of string keys, choosing bits from any
 * any fix location close to the tail of those keys would usually be good
 * enough to prevent high collision rates.
 */
apr_hashfunc_t optimized for the key that we use in SVN: paths and
property names.  Its primary goal is speed for keys of known length.

Since strings tend to spawn large value spaces (usually differ in many
bits with differences spanning a larger section of the key), we can be
quite sloppy extracting a hash value.  The more keys there are in a
hash container, the more bits of the value returned by this function
will be used.  For a small number of string keys, choosing bits from any
any fix location close to the tail of those keys would usually be good
enough to prevent high collision rates.
apr_hashfunc_t optimized for the key that we use in SVN : paths and property names . Its primary goal is speed for keys of known length . Since strings tend to spawn large value spaces ( usually differ in many bits with differences spanning a larger section of the key ) we can be quite sloppy extracting a hash value . The more keys there are in a hash container the more bits of the value returned by this function will be used . For a small number of string keys choosing bits from any any fix location close to the tail of those keys would usually be good enough to prevent high collision rates .
static unsigned int
hashfunc_compatible(const char *char_key, apr_ssize_t *klen)
{
    unsigned int hash = 0;
    const unsigned char *key = (const unsigned char *)char_key;
    const unsigned char *p;
    apr_ssize_t i;
    if (*klen == APR_HASH_KEY_STRING)
      *klen = strlen(char_key);
#if SVN_UNALIGNED_ACCESS_IS_OK
    for (p = key, i = *klen; i >= 4; i-=4, p+=4)
      {
        apr_uint32_t chunk = *(const apr_uint32_t *)p;
        hash = hash * 33 * 33 * 33 * 33 + chunk + (chunk >> 17);
      }
#else
    for (p = key, i = *klen; i >= 4; i-=4, p+=4)
      {
        hash = hash * 33 * 33 * 33 * 33
              + p[0] * 33 * 33 * 33
              + p[1] * 33 * 33
              + p[2] * 33
              + p[3];
      }
#endif
    for (; i; i--, p++)
        hash = hash * 33 + *p;
    return hash;
}
static unsigned int hashfunc_compatible ( const char * char_key , apr_ssize_t * klen ) { unsigned int hash = 0 ; const unsigned char * key = ( const unsigned char * ) char_key ; const unsigned char * p ; apr_ssize_t i ; if ( * klen == APR_HASH_KEY_STRING ) * klen = strlen ( char_key ) ; #if SVN_UNALIGNED_ACCESS_IS_OK for ( p = key , i = * klen ; i >= 4 ; i -= 4 , p += 4 ) { apr_uint32_t chunk = * ( const apr_uint32_t * ) p ; hash = hash * 33 * 33 * 33 * 33 + chunk + ( chunk >> 17 ) ; } #else for ( p = key , i = * klen ; i >= 4 ; i -= 4 , p += 4 ) { hash = hash * 33 * 33 * 33 * 33 + p [ 0 ] * 33 * 33 * 33 + p [ 1 ] * 33 * 33 + p [ 2 ] * 33 + p [ 3 ] ; } #endif for ( ; i ; i -- , p ++ ) hash = hash * 33 + * p ; return hash ; }
apr_hashfunc_t optimized for the key that we use in SVN: paths and
 property names.
apr_hashfunc_t optimized for the key that we use in SVN : paths and property names .
/* the ">> 17" part gives upper bits in the chunk a chance to make
           some impact as well */