123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- /*
- * $Id$
- *
- * Copyright (C) 2006 iptelorg GmbH
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- /*
- * History:
- * --------
- * 2006-02-02 created by andrei
- * 2006-11-24 added numeric string optimized hash function (andrei)
- * 2006-12-13 split into hashes.h (more generic) and str_hash.h (andrei)
- * 2007-02-22 added case insensitive versions (andrei)
- */
- #ifndef _hashes_h
- #define _hashes_h
- #include "str.h"
- /* internal use: hash update
- * params: char* s - string start,
- * char* end - end
- * char* p, and unsigned v temporary vars (used)
- * unsigned h - result
- * h should be initialized (e.g. set it to 0), the result in h */
- #define hash_update_str(s, end, p, v, h) \
- do{ \
- for ((p)=(s); (p)<=((end)-4); (p)+=4){ \
- (v)=(*(p)<<24)+((p)[1]<<16)+((p)[2]<<8)+(p)[3]; \
- (h)+=(v)^((v)>>3); \
- } \
- switch((end)-(p)){\
- case 3: \
- (v)=(*(p)<<16)+((p)[1]<<8)+(p)[2]; break; \
- case 2: \
- (v)=(*(p)<<8)+p[1]; break; \
- case 1: \
- (v)=*p; break; \
- default: \
- (v)=0; break; \
- } \
- (h)+=(v)^((v)>>3); \
- }while(0)
- /* like hash_update_str, but case insensitive
- * params: char* s - string start,
- * char* end - end
- * char* p, and unsigned v temporary vars (used)
- * unsigned h - result
- * h should be initialized (e.g. set it to 0), the result in h */
- #define hash_update_case_str(s, end, p, v, h) \
- do{ \
- for ((p)=(s); (p)<=((end)-4); (p)+=4){ \
- (v)=((*(p)<<24)+((p)[1]<<16)+((p)[2]<<8)+(p)[3])|0x20202020; \
- (h)+=(v)^((v)>>3); \
- } \
- (v)=0; \
- for (;(p)<(end); (p)++){ (v)<<=8; (v)+=*(p)|0x20;} \
- (h)+=(v)^((v)>>3); \
- }while(0)
- /* internal use: call it to adjust the h from hash_update_str */
- #define hash_finish(h) (((h)+((h)>>11))+(((h)>>13)+((h)>>23)))
- /* "raw" 2 strings hash
- * returns an unsigned int (which you can use modulo table_size as hash value)
- */
- inline static unsigned int get_hash2_raw(const str* key1, const str* key2)
- {
- char* p;
- register unsigned v;
- register unsigned h;
-
- h=0;
-
- hash_update_str(key1->s, key1->s+key1->len, p, v, h);
- hash_update_str(key2->s, key2->s+key2->len, p, v, h);
- return hash_finish(h);
- }
- /* "raw" 1 string hash
- * returns an unsigned int (which you can use modulo table_size as hash value)
- */
- inline static unsigned int get_hash1_raw(const char* s, int len)
- {
- const char* p;
- register unsigned v;
- register unsigned h;
-
- h=0;
-
- hash_update_str(s, s+len, p, v, h);
- return hash_finish(h);
- }
- /* a little slower than hash_* , but better distribution for
- * numbers and about the same for strings */
- #define hash_update_str2(s, end, p, v, h) \
- do{ \
- for ((p)=(s); (p)<=((end)-4); (p)+=4){ \
- (v)=(*(p)*16777213)+((p)[1]*65537)+((p)[2]*257)+(p)[3]; \
- (h)=16777259*(h)+((v)^((v)<<17)); \
- } \
- (v)=0; \
- for (;(p)<(end); (p)++){ (v)*=251; (v)+=*(p);} \
- (h)=16777259*(h)+((v)^((v)<<17)); \
- }while(0)
- /* like hash_update_str2 but case insensitive */
- #define hash_update_case_str2(s, end, p, v, h) \
- do{ \
- for ((p)=(s); (p)<=((end)-4); (p)+=4){ \
- (v)=((*(p)|0x20)*16777213)+(((p)[1]|0x20)*65537)+\
- (((p)[2]|0x20)*257)+((p)[3]|0x20); \
- (h)=16777259*(h)+((v)^((v)<<17)); \
- } \
- (v)=0; \
- for (;(p)<(end); (p)++){ (v)*=251; (v)+=*(p)|0x20;} \
- (h)=16777259*(h)+((v)^((v)<<17)); \
- }while(0)
- /* internal use: call it to adjust the h from hash_update_str */
- #define hash_finish2(h) (((h)+((h)>>7))+(((h)>>13)+((h)>>23)))
- /* a little slower than get_hash1_raw() , but better distribution for
- * numbers and about the same for strings */
- inline static unsigned int get_hash1_raw2(const char* s, int len)
- {
- const char* p;
- register unsigned v;
- register unsigned h;
-
- h=0;
-
- hash_update_str2(s, s+len, p, v, h);
- return hash_finish2(h);
- }
- /* "raw" 2 strings hash optimized for numeric strings (see above)
- * returns an unsigned int (which you can use modulo table_size as hash value)
- */
- inline static unsigned int get_hash2_raw2(const str* key1, const str* key2)
- {
- char* p;
- register unsigned v;
- register unsigned h;
-
- h=0;
-
- hash_update_str2(key1->s, key1->s+key1->len, p, v, h);
- hash_update_str2(key2->s, key2->s+key2->len, p, v, h);
- return hash_finish2(h);
- }
- /* "raw" 2 strings case insensitive hash (like get_hash2_raw but case
- * insensitive)
- * returns an unsigned int (which you can use modulo table_size as hash value)
- */
- inline static unsigned int get_hash2_case_raw(const str* key1, const str* key2)
- {
- char* p;
- register unsigned v;
- register unsigned h;
-
- h=0;
-
- hash_update_case_str(key1->s, key1->s+key1->len, p, v, h);
- hash_update_case_str(key2->s, key2->s+key2->len, p, v, h);
- return hash_finish(h);
- }
- /* "raw" 1 string case insensitive hash
- * returns an unsigned int (which you can use modulo table_size as hash value)
- */
- inline static unsigned int get_hash1_case_raw(const char* s, int len)
- {
- const char* p;
- register unsigned v;
- register unsigned h;
-
- h=0;
-
- hash_update_case_str(s, s+len, p, v, h);
- return hash_finish(h);
- }
- /* same as get_hash1_raw2, but case insensitive and slower
- * returns an unsigned int (which you can use modulo table_size as hash value)
- */
- inline static unsigned int get_hash1_case_raw2(const char* s, int len)
- {
- const char* p;
- register unsigned v;
- register unsigned h;
-
- h=0;
-
- hash_update_case_str2(s, s+len, p, v, h);
- return hash_finish2(h);
- }
- /* "raw" 2 strings hash optimized for numeric strings (see above)
- * same as get_hash2_raw2 but case insensitive and slower
- * returns an unsigned int (which you can use modulo table_size as hash value)
- */
- inline static unsigned int get_hash2_case_raw2(const str* key1,
- const str* key2)
- {
- char* p;
- register unsigned v;
- register unsigned h;
-
- h=0;
-
- hash_update_case_str2(key1->s, key1->s+key1->len, p, v, h);
- hash_update_case_str2(key2->s, key2->s+key2->len, p, v, h);
- return hash_finish2(h);
- }
- #endif
|