00001
00002 #ifndef _GK_NAME_H
00003 #define _GK_NAME_H
00004
00005 #include <string>
00006 #include <cstring>
00007 #include <cassert>
00008
00009
00010 namespace gk {
00011
00012 #define GK_NAME_MAX 44
00013 #define GK_NAME_HASH_SEED 1
00014
00015
00016
00017
00018
00019
00020
00021 class Name
00022 {
00023 #ifndef GK_NAME_NOSTRING
00024 char m_name[GK_NAME_MAX];
00025 #endif
00026 unsigned int m_hash;
00027
00028
00029 static
00030 unsigned int murmur2( const char *string, const int length, const unsigned int seed )
00031 {
00032
00033
00034 const unsigned int m = 0x5bd1e995;
00035 const int r = 24;
00036
00037
00038 unsigned int h = seed ^ length;
00039 int len= length;
00040
00041
00042 const unsigned char *data = (const unsigned char *) string;
00043 while(len >= 4)
00044 {
00045 unsigned int k = * (const unsigned int *) data;
00046
00047 k *= m;
00048 k ^= k >> r;
00049 k *= m;
00050
00051 h *= m;
00052 h ^= k;
00053
00054 data += 4;
00055 len -= 4;
00056 }
00057
00058
00059 switch(len)
00060 {
00061 case 3: h ^= data[2] << 16;
00062 case 2: h ^= data[1] << 8;
00063 case 1: h ^= data[0];
00064 h *= m;
00065 };
00066
00067
00068
00069 h ^= h >> 13;
00070 h *= m;
00071 h ^= h >> 15;
00072
00073 return h;
00074 }
00075
00076 void hash( const char *string )
00077 {
00078 m_hash= murmur2(string, GK_NAME_MAX, GK_NAME_HASH_SEED);
00079 }
00080
00081 public:
00082
00083 Name( )
00084 :
00085 m_hash(0)
00086 {
00087 #ifndef GK_NAME_NOSTRING
00088 m_name[0]= 0;
00089 #endif
00090 }
00091
00092
00093 Name( const char *string )
00094 {
00095 #ifndef GK_NAME_NOSTRING
00096 strncpy(m_name, string, GK_NAME_MAX);
00097 m_name[GK_NAME_MAX -1]= 0;
00098 hash(m_name);
00099
00100 #else
00101 char name[GK_NAME_MAX];
00102 strncpy(name, string, GK_NAME_MAX);
00103 name[GK_NAME_MAX -1]= 0;
00104 hash(name);
00105 #endif
00106 }
00107
00108
00109 Name( const std::string& string )
00110 {
00111 #ifndef GK_NAME_NOSTRING
00112 strncpy(m_name, string.c_str(), GK_NAME_MAX);
00113 m_name[GK_NAME_MAX -1]= 0;
00114 hash(m_name);
00115
00116 #else
00117 char name[GK_NAME_MAX];
00118 strncpy(name, string.c_str(), GK_NAME_MAX);
00119 name[GK_NAME_MAX -1]= 0;
00120 hash(name);
00121 #endif
00122 }
00123
00124
00125 Name( const Name& b )
00126 {
00127 #ifndef GK_NAME_NOSTRING
00128 strcpy(m_name, b.m_name);
00129 #endif
00130 m_hash= b.m_hash;
00131 }
00132
00133
00134 Name& operator=( const Name&b )
00135 {
00136 #ifndef GK_NAME_NOSTRING
00137 strcpy(m_name, b.m_name);
00138 #endif
00139 m_hash= b.m_hash;
00140 return *this;
00141 }
00142
00143 unsigned int hash( ) const
00144 {
00145 return m_hash;
00146 }
00147
00148 #if 1
00149
00150 const char *c_str( ) const
00151 {
00152 #ifndef GK_NAME_NOSTRING
00153 return m_name;
00154 #else
00155 return "(Name NOSTRING)";
00156 #endif
00157 }
00158
00159
00160 const char *c_str( )
00161 {
00162 #ifndef GK_NAME_NOSTRING
00163 return m_name;
00164 #else
00165 return "(Name NOSTRING)";
00166 #endif
00167 }
00168 #endif
00169
00170
00171 friend bool operator==( const Name& a, const Name& b );
00172
00173 friend bool operator!=( const Name& a, const Name& b );
00174
00175 friend bool operator<( const Name& a, const Name& b );
00176
00177 friend bool operator>( const Name& a, const Name& b );
00178
00179 friend int compare( const Name& a, const Name& b );
00180
00181 static
00182 unsigned int getHash( const char * string )
00183 {
00184 return murmur2(string, strlen(string), GK_NAME_HASH_SEED);
00185 }
00186
00187 static
00188 unsigned int getHash( const std::string& string )
00189 {
00190 return murmur2(string.c_str(), string.size(), GK_NAME_HASH_SEED);
00191 }
00192
00193
00194
00195 };
00196
00197 inline
00198 bool operator==( const Name& a, const Name& b )
00199 {
00200
00201 #ifndef GK_NAME_NOSTRING
00202
00203 const bool hash= (a.m_hash == b.m_hash);
00204 const int cmp= strcmp(a.m_name, b.m_name);
00205 assert((hash == true && cmp == 0) || (hash == false && cmp != 0));
00206 #endif
00207
00208 return (a.m_hash == b.m_hash);
00209 }
00210
00211 inline
00212 bool operator!=( const Name& a, const Name& b)
00213 {
00214
00215 #ifndef GK_NAME_NOSTRING
00216
00217 const bool hash= (a.m_hash == b.m_hash);
00218 const int cmp= strcmp(a.m_name, b.m_name);
00219 assert((hash == true && cmp == 0) || (hash == false && cmp != 0));
00220 #endif
00221
00222 return (a.m_hash != b.m_hash);
00223 }
00224
00225 inline
00226 bool operator>( const Name& a, const Name& b )
00227 {
00228
00229 #ifndef GK_NAME_NOSTRING
00230
00231 const bool hash= (a.m_hash == b.m_hash);
00232 const int cmp= strcmp(a.m_name, b.m_name);
00233 assert((hash == true && cmp == 0) || (hash == false && cmp != 0));
00234 #endif
00235
00236 return (a.m_hash > b.m_hash);
00237 }
00238
00239 inline
00240 bool operator<( const Name& a, const Name& b )
00241 {
00242
00243 #ifndef GK_NAME_NOSTRING
00244
00245 const bool hash= (a.m_hash == b.m_hash);
00246 const int cmp= strcmp(a.m_name, b.m_name);
00247 assert((hash == true && cmp == 0) || (hash == false && cmp != 0));
00248 #endif
00249
00250 return (a.m_hash < b.m_hash);
00251 }
00252
00253 inline
00254 int compare( const Name& a, const Name& b )
00255 {
00256
00257 #ifndef GK_NAME_NOSTRING
00258
00259 const bool hash= (a.m_hash == b.m_hash);
00260 const int cmp= strcmp(a.m_name, b.m_name);
00261 assert((hash == true && cmp == 0) || (hash == false && cmp != 0));
00262 #endif
00263
00264 if(a.m_hash < b.m_hash)
00265 return -1;
00266 else if(a.m_hash > b.m_hash)
00267 return 1;
00268 else
00269 return 0;
00270 }
00271
00272 }
00273
00274 #endif
00275