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 40
00013 #define GK_NAME_HASH_SEED 1
00014
00015
00016
00017
00018 class Name
00019 {
00020 #ifndef GK_NAME_NOSTRING
00021 char m_name[GK_NAME_MAX];
00022 #endif
00023
00024 unsigned int m_hash;
00025 int m_id;
00026
00027
00028 static
00029 unsigned int murmur2( const char *string, const int length, const unsigned int seed )
00030 {
00031
00032
00033 const unsigned int m = 0x5bd1e995;
00034 const int r = 24;
00035
00036
00037 unsigned int h = seed ^ length;
00038 int len= length;
00039
00040
00041 const unsigned char *data = (const unsigned char *) string;
00042 while(len >= 4)
00043 {
00044 unsigned int k = * (const unsigned int *) data;
00045
00046 k *= m;
00047 k ^= k >> r;
00048 k *= m;
00049
00050 h *= m;
00051 h ^= k;
00052
00053 data += 4;
00054 len -= 4;
00055 }
00056
00057
00058 switch(len)
00059 {
00060 case 3: h ^= data[2] << 16;
00061 case 2: h ^= data[1] << 8;
00062 case 1: h ^= data[0];
00063 h *= m;
00064 };
00065
00066
00067
00068 h ^= h >> 13;
00069 h *= m;
00070 h ^= h >> 15;
00071
00072 return h;
00073 }
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 m_id(-1)
00087 {
00088 #ifndef GK_NAME_NOSTRING
00089 m_name[0]= 0;
00090 #endif
00091 }
00092
00093
00094 Name( const int id )
00095 :
00096 m_hash(0),
00097 m_id(id)
00098 {
00099 #ifndef GK_NAME_NOSTRING
00100 m_name[0]= 0;
00101 #endif
00102 }
00103
00104
00105 Name( const char *string )
00106 :
00107 m_hash(0),
00108 m_id(-1)
00109 {
00110 #ifndef GK_NAME_NOSTRING
00111 strncpy(m_name, string, GK_NAME_MAX);
00112 m_name[GK_NAME_MAX -1]= 0;
00113 hash(m_name);
00114
00115 #else
00116 char name[GK_NAME_MAX];
00117 strncpy(name, string, GK_NAME_MAX);
00118 name[GK_NAME_MAX -1]= 0;
00119 hash(name);
00120 #endif
00121 }
00122
00123
00124 Name( const std::string& string )
00125 :
00126 m_hash(0),
00127 m_id(-1)
00128 {
00129 #ifndef GK_NAME_NOSTRING
00130 strncpy(m_name, string.c_str(), GK_NAME_MAX);
00131 m_name[GK_NAME_MAX -1]= 0;
00132 hash(m_name);
00133
00134 #else
00135 char name[GK_NAME_MAX];
00136 strncpy(name, string.c_str(), GK_NAME_MAX);
00137 name[GK_NAME_MAX -1]= 0;
00138 hash(name);
00139 #endif
00140 }
00141
00142
00143 Name( const char *string, const int id )
00144 :
00145 m_hash(0),
00146 m_id(id)
00147 {
00148 #ifndef GK_NAME_NOSTRING
00149 strncpy(m_name, string, GK_NAME_MAX);
00150 m_name[GK_NAME_MAX -1]= 0;
00151 hash(m_name);
00152
00153 #else
00154 char name[GK_NAME_MAX];
00155 strncpy(name, string, GK_NAME_MAX);
00156 name[GK_NAME_MAX -1]= 0;
00157 hash(name);
00158 #endif
00159 }
00160
00161
00162 Name( const std::string& string, const int id )
00163 :
00164 m_hash(0),
00165 m_id(id)
00166 {
00167 #ifndef GK_NAME_NOSTRING
00168 strncpy(m_name, string.c_str(), GK_NAME_MAX);
00169 m_name[GK_NAME_MAX -1]= 0;
00170 hash(m_name);
00171
00172 #else
00173 char name[GK_NAME_MAX];
00174 strncpy(name, string.c_str(), GK_NAME_MAX);
00175 name[GK_NAME_MAX -1]= 0;
00176 hash(name);
00177 #endif
00178 }
00179
00180
00181 Name( const Name& b )
00182 {
00183 #ifndef GK_NAME_NOSTRING
00184 strcpy(m_name, b.m_name);
00185 #endif
00186 m_hash= b.m_hash;
00187 m_id= b.m_id;
00188 }
00189
00190
00191 Name& operator=( const Name&b )
00192 {
00193 #ifndef GK_NAME_NOSTRING
00194 strcpy(m_name, b.m_name);
00195 #endif
00196 m_hash= b.m_hash;
00197 m_id= b.m_id;
00198 return *this;
00199 }
00200
00201
00202 unsigned int hash( ) const
00203 {
00204 return m_hash;
00205 }
00206
00207
00208 unsigned int id( ) const
00209 {
00210 return m_id;
00211 }
00212
00213
00214 const char *c_str( ) const
00215 {
00216 #ifndef GK_NAME_NOSTRING
00217 return m_name;
00218 #else
00219 return "(Name NOSTRING)";
00220 #endif
00221 }
00222
00223
00224 const char *c_str( )
00225 {
00226 #ifndef GK_NAME_NOSTRING
00227 return m_name;
00228 #else
00229 return "(Name NOSTRING)";
00230 #endif
00231 }
00232
00233
00234 friend bool operator==( const Name& a, const Name& b );
00235
00236 friend bool operator!=( const Name& a, const Name& b );
00237
00238 friend bool operator<( const Name& a, const Name& b );
00239
00240 friend bool operator>( const Name& a, const Name& b );
00241
00242 friend int compare( const Name& a, const Name& b );
00243
00244
00245 static
00246 unsigned int getHash( const char * string )
00247 {
00248 return murmur2(string, strlen(string), GK_NAME_HASH_SEED);
00249 }
00250
00251
00252 static
00253 unsigned int getHash( const std::string& string )
00254 {
00255 return murmur2(string.c_str(), string.size(), GK_NAME_HASH_SEED);
00256 }
00257
00258
00259
00260 };
00261
00262 inline
00263 bool operator==( const Name& a, const Name& b )
00264 {
00265 if(a.m_id < 0 || b.m_id < 0)
00266 {
00267 #ifdef GK_NAME_NOSTRING
00268 return (a.m_hash == b.m_hash);
00269 #else
00270 return (a.m_hash == b.m_hash) && (strcmp(a.m_name, b.m_name) == 0);
00271 #endif
00272 }
00273 else
00274 {
00275 return (a.m_id == b.m_id);
00276 }
00277 }
00278
00279 inline
00280 bool operator!=( const Name& a, const Name& b )
00281 {
00282 if(a.m_id < 0 || b.m_id < 0)
00283 return (a.m_hash != b.m_hash);
00284 else
00285 return (a.m_id != b.m_id);
00286 }
00287
00288 inline
00289 bool operator>( const Name& a, const Name& b )
00290 {
00291 if(a.m_id < 0 || b.m_id < 0)
00292 return (a.m_hash > b.m_hash);
00293 else
00294 return (a.m_id > b.m_id);
00295 }
00296
00297 inline
00298 bool operator<( const Name& a, const Name& b )
00299 {
00300 if(a.m_id < 0 || b.m_id < 0)
00301 return (a.m_hash < b.m_hash);
00302 else
00303 return (a.m_id < b.m_id);}
00304
00305 inline
00306 int compare( const Name& a, const Name& b )
00307 {
00308 if(a.m_id < 0 || b.m_id < 0)
00309 {
00310 if(a.m_hash < b.m_hash)
00311 return -1;
00312 else if(a.m_hash > b.m_hash)
00313 return 1;
00314 else
00315 #ifdef GK_NAME_NOSTRING
00316 return 0;
00317 #else
00318 return strcmp(a.m_name, b.m_name);
00319 #endif
00320 }
00321 else
00322 {
00323 if(a.m_id < b.m_id)
00324 return -1;
00325 else if(a.m_id > b.m_id)
00326 return 1;
00327 else
00328 return 0;
00329 }
00330 }
00331
00332 }
00333
00334 #endif
00335