00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifdef USE_PCH
00038 #include "common_com_pch.h"
00039 #endif
00040 #pragma hdrstop
00041
00042 #include <alloca.h>
00043 #include <string.h>
00044
00045 #include <map>
00046 #include "HashTable.h"
00047 using namespace stlCompatibility;
00048
00049
00050 #ifdef _SGI_SGI
00051 #include <utility>
00052 #endif
00053
00054 using namespace std;
00055
00056 #include "defs.h"
00057 #include "errors.h"
00058 #include "cxx_memory.h"
00059
00060 #include "strtab.h"
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 typedef UINT32 STR_INDEX;
00075
00076 #ifdef linux
00077
00078 #define STR_INDEX_size(xxx) (xxx & 0xff)
00079 #define STR_INDEX_index(xxx) (xxx >> 8)
00080
00081 #else
00082
00083
00084
00085
00086
00087 static inline mUINT8
00088 STR_INDEX_size (STR_INDEX idx) { return idx & 0xff; }
00089 static inline mUINT32
00090 STR_INDEX_index (STR_INDEX idx) { return idx >> 8; }
00091
00092 #endif
00093
00094
00095
00096
00097
00098 static inline STR_INDEX
00099 make_STR_INDEX (UINT32 size, UINT32 idx)
00100 {
00101
00102 if (size > 0xff)
00103 size = 0xff;
00104 return (STR_INDEX) ((idx << 8) | size);
00105 }
00106
00107 struct NULL_TERMINATED_STRING
00108 {
00109 static char *get_str (char *buffer) {
00110 return buffer;
00111 }
00112
00113 static const char *get_str (const char *buffer) {
00114 return buffer;
00115 }
00116
00117 static UINT32 get_length (const char *buffer) {
00118 return strlen (buffer);
00119 }
00120
00121 static UINT32 get_buffer_length (UINT32 length) {
00122 return length + 1;
00123 }
00124
00125 static void copy (const char *str, UINT32 length, char *buffer) {
00126 memcpy (buffer, str, length+1);
00127 }
00128 };
00129
00130
00131 union UNALIGN_INT32
00132 {
00133 char ch[sizeof(UINT32)];
00134 UINT32 n;
00135
00136 UNALIGN_INT32 (UINT32 x) : n (x) {}
00137
00138 UNALIGN_INT32 (const char *s) {
00139 for (INT32 i = 0; i < sizeof(UINT32); ++i)
00140 ch[i] = *s++;
00141 }
00142 };
00143
00144
00145 struct CHARACTER_ARRAY
00146 {
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 #define UC(x) ((unsigned char)(x))
00162
00163
00164
00165
00166
00167
00168 static const char *get_str (const char *buffer) {
00169 if (UC(*buffer) != 0xff)
00170 return buffer + 1;
00171 else
00172 return buffer + sizeof(UINT32) + 1;
00173 }
00174
00175 static char *get_str (char *buffer) {
00176 if (UC(*buffer) != 0xff)
00177 return buffer + 1;
00178 else
00179 return buffer + sizeof(UINT32) + 1;
00180 }
00181
00182 static UINT32 get_length (const char *buffer) {
00183 if (UC(*buffer) != 0xff)
00184
00185
00186 return UC(*buffer);
00187 else {
00188 UNALIGN_INT32 unalign (buffer + 1);
00189 return unalign.n;
00190 }
00191 }
00192
00193 static UINT32 get_buffer_length (UINT32 length) {
00194 return length < 0xff ? length + 1 : length + 1 + sizeof(UINT32);
00195 }
00196
00197 static void copy (const char *str, UINT32 length, char *buffer_) {
00198 unsigned char *buffer = (unsigned char *) buffer_;
00199 if (length < 0xff) {
00200 *buffer++ = length;
00201 } else {
00202 *buffer++ = 0xff;
00203 UNALIGN_INT32 unalign (length);
00204 for (INT32 i = 0; i < sizeof(UINT32); ++i)
00205 *buffer++ = unalign.ch[i];
00206 }
00207 memcpy (buffer, str, length);
00208 }
00209
00210 };
00211
00212
00213 template <class STR>
00214 struct STR_TAB
00215 {
00216 char *buffer;
00217 STR_IDX last_idx;
00218 UINT32 buffer_size;
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 struct StringHashKey {
00241 mUINT32 idx;
00242 mUINT32 size;
00243
00244 StringHashKey() {}
00245
00246 StringHashKey(mUINT32 _idx, mUINT32 _size) :
00247 idx(_idx), size(_size) {}
00248
00249 StringHashKey(const StringHashKey& shk) :
00250 idx(shk.idx), size(shk.size) {}
00251
00252 StringHashKey& operator=(const StringHashKey& shk) {
00253 if (this != &shk) {
00254 idx = shk.idx;
00255 size = shk.size;
00256 }
00257 return (*this);
00258 }
00259 };
00260
00261
00262
00263 class ExtractStringBufferFromStringTable {
00264 const STR_TAB<STR>& stringTable;
00265
00266 public:
00267 ExtractStringBufferFromStringTable (const STR_TAB<STR>& _stringTable) :
00268 stringTable(_stringTable) {}
00269
00270 char * operator() (mUINT32 idx) const {
00271 char *str = stringTable.buffer + idx;
00272 return STR::get_str(str);
00273 }
00274 };
00275
00276 ExtractStringBufferFromStringTable extractStringBufferFromStringTable;
00277
00278 class HashStringHashKey {
00279 public:
00280 STR_TAB<STR> *thisEnclosing;
00281
00282 HashStringHashKey() : thisEnclosing(NULL) {}
00283
00284 HashStringHashKey(STR_TAB<STR> & _thisEnclosing) :
00285 thisEnclosing(&_thisEnclosing) {}
00286
00287 UINT32 operator() (const StringHashKey& key) const {
00288 char * str = thisEnclosing->extractStringBufferFromStringTable(key.idx);
00289
00290 UINT32 h = 0;
00291 const UINT32 length = key.size;
00292 for (UINT32 i = 0; i < length; ++i)
00293 h = 5 * h + str[i];
00294 return h;
00295 }
00296 };
00297
00298 class EqStringHashKey {
00299 public:
00300 STR_TAB<STR> *thisEnclosing;
00301
00302 EqStringHashKey() :
00303 thisEnclosing(NULL) {}
00304
00305 EqStringHashKey(STR_TAB<STR> & _thisEnclosing) :
00306 thisEnclosing(&_thisEnclosing) {}
00307
00308 bool operator() (const StringHashKey& key1,
00309 const StringHashKey& key2) const {
00310 if (key1.size != key2.size) return false;
00311 char * str1 = thisEnclosing->extractStringBufferFromStringTable(key1.idx);
00312 char * str2 = thisEnclosing->extractStringBufferFromStringTable(key2.idx);
00313 bool result = (str1[0] == str2[0]) &&
00314 (memcmp(str1, str2, key1.size) == 0);
00315 return result;
00316 }
00317 };
00318
00319 typedef HashTable<StringHashKey, STR_INDEX, HashStringHashKey, EqStringHashKey> HASHTABLE;
00320 HASHTABLE hash_table;
00321
00322 STR_TAB(UINT bucket_size) :
00323 hash_table(),
00324 extractStringBufferFromStringTable(*this),
00325 buffer (NULL), last_idx (0), buffer_size (0) {
00326 hash_table.hashClass().thisEnclosing = this;
00327 hash_table.eqClass().thisEnclosing = this;
00328 };
00329
00330
00331 void reserve (UINT32 size) {
00332 if (size > buffer_size - last_idx) {
00333
00334 while (size > buffer_size - last_idx) {
00335 if (buffer_size < 0x100000)
00336 buffer_size *= 2;
00337 else
00338 buffer_size += 0x80000;
00339 }
00340 buffer = (char *) MEM_POOL_Realloc (Malloc_Mem_Pool, buffer, 0,
00341 buffer_size);
00342 }
00343 }
00344
00345 void init_hash ();
00346
00347 UINT32 insert (const char *str, UINT32 size);
00348
00349 UINT32 insert (const char *str) {
00350 return insert (str, strlen (str));
00351 }
00352
00353 void copy_str (const char *str, UINT32 size);
00354
00355 void dump(FILE *fout) {
00356
00357 }
00358 };
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 template <class STR>
00369 UINT32 STR_TAB<STR>::insert (const char *str, UINT32 size)
00370 {
00371
00372
00373 UINT32 oldLastIndex = last_idx;
00374 copy_str (str, size);
00375 STR_INDEX new_index = make_STR_INDEX (size, oldLastIndex);
00376
00377
00378 typename HASHTABLE::ValueBoolPair insertStatus =
00379 hash_table.insert(typename HASHTABLE::KeyValuePair(StringHashKey(oldLastIndex, size), new_index));
00380
00381 if (insertStatus.second == false) {
00382
00383
00384 last_idx = oldLastIndex;
00385 return STR_INDEX_index(insertStatus.first);
00386 } else {
00387
00388 assert(STR_INDEX_index(insertStatus.first) == oldLastIndex);
00389 return oldLastIndex;
00390 }
00391 }
00392
00393
00394 template <class STR>
00395 void STR_TAB<STR>::copy_str (const char *str, UINT32 size) {
00396 UINT32 buffer_size = STR::get_buffer_length (size);
00397 reserve (buffer_size);
00398 STR::copy (str, size, buffer + last_idx);
00399 last_idx += buffer_size;
00400 }
00401
00402
00403 template <class STR>
00404 void STR_TAB<STR>::init_hash () {
00405 UINT32 idx = 1;
00406 while (idx < last_idx) {
00407 UINT32 length = STR::get_length(buffer + idx);
00408
00409 STR_INDEX new_index = make_STR_INDEX(length, idx);
00410 hash_table.insert(typename HASHTABLE::KeyValuePair(StringHashKey(idx, length), new_index));
00411 idx += STR::get_buffer_length (length);
00412 }
00413 }
00414
00415
00416 template <class STRTAB>
00417 static inline void initialize_strtab (STRTAB& strtab, UINT32 size) {
00418 strtab.buffer_size = size;
00419 strtab.buffer = (char *) MEM_POOL_Alloc (Malloc_Mem_Pool, size);
00420 strtab.buffer[0] = 0;
00421 strtab.last_idx = 1;
00422 }
00423
00424
00425 template <class STRTAB>
00426 static inline void initialize_strtab (STRTAB& strtab, const char *buf, UINT32 size) {
00427 strtab.hash_table.clear();
00428 strtab.buffer_size = size;
00429 strtab.buffer = (char *) MEM_POOL_Alloc (Malloc_Mem_Pool, size);
00430 memmove (strtab.buffer, buf, size);
00431 strtab.last_idx = size;
00432 strtab.init_hash ();
00433 }
00434
00435
00436
00437 static STR_TAB<NULL_TERMINATED_STRING> Strtab (1000);
00438
00439 STRING_TABLE Str_Table;
00440
00441 UINT32
00442 STR_Table_Size () {
00443 return Strtab.last_idx;
00444 }
00445
00446
00447 void
00448 Initialize_Strtab (UINT32 size) {
00449 initialize_strtab (Strtab, size);
00450 }
00451
00452
00453 void Initialize_Strtab (const char *buf, UINT32 size) {
00454 initialize_strtab (Strtab, buf, size);
00455 }
00456
00457
00458 STR_IDX Save_Str (const char *str) {
00459 if (str == NULL) return 0;
00460 return Strtab.insert (str);
00461 }
00462
00463
00464 STR_IDX Save_Str2 (const char *s1, const char *s2) {
00465 UINT len = strlen (s1) + strlen(s2) + 1;
00466 char *new_str = (char *) alloca (len);
00467 strcpy (new_str, s1);
00468 strcat (new_str, s2);
00469 return Save_Str (new_str);
00470 }
00471
00472 STR_IDX Save_Str2i (const char *s1, const char *s2, UINT i) {
00473 UINT len = strlen (s1) + strlen(s2) + 17;
00474 char *new_str = (char *) alloca (len);
00475 sprintf(new_str, "%s%s%d", s1, s2, i);
00476 return Save_Str (new_str);
00477 }
00478
00479 char * Index_To_Str (STR_IDX idx) {
00480 Is_True (idx < Strtab.last_idx, ("Invalid STR_IDX"));
00481 return NULL_TERMINATED_STRING::get_str (Strtab.buffer + idx);
00482 }
00483
00484
00485 const UINT32 TCON_STRTAB_HASH_SIZE = 512;
00486 static STR_TAB<CHARACTER_ARRAY> TCON_strtab (TCON_STRTAB_HASH_SIZE);
00487
00488 UINT32
00489 TCON_strtab_size () {
00490 return TCON_strtab.last_idx;
00491 }
00492
00493 char * TCON_strtab_buffer () {
00494 return TCON_strtab.buffer;
00495 }
00496
00497
00498 void Initialize_TCON_strtab (UINT32 size) {
00499 initialize_strtab (TCON_strtab, size);
00500 }
00501
00502
00503 void Initialize_TCON_strtab (const char *buf, UINT32 size) {
00504 initialize_strtab (TCON_strtab, buf, size);
00505 }
00506
00507
00508 UINT32 Save_StrN (const char *s1, UINT32 len) {
00509 if (len == 0) return 0;
00510 return TCON_strtab.insert(s1, len);
00511
00512 }
00513
00514 char * Index_to_char_array (UINT32 idx) {
00515 Is_True (idx < TCON_strtab.last_idx, ("Invalid TCON str index"));
00516 return CHARACTER_ARRAY::get_str (TCON_strtab.buffer + idx);
00517 }
00518
00519 #ifdef MONGOOSE_BE
00520
00521 template <class STR, class MAP>
00522 void merge_strtab (STR_TAB<STR>& strtab, const char *buf, UINT32 size, MAP& map) {
00523 map[0] = 0;
00524 UINT32 idx = 1;
00525 while (idx < size) {
00526 const char *str = STR::get_str (buf + idx);
00527 UINT32 size = STR::get_length (buf + idx);
00528 UINT32 new_idx = strtab.insert (str, size);
00529 map[idx] = new_idx;
00530 idx += STR::get_buffer_length (size);
00531 }
00532 }
00533
00534
00535
00536
00537
00538 void
00539 Merge_Strtab (const char *buf, UINT32 size, STR_IDX_MAP& map) {
00540 merge_strtab (Strtab, buf, size, map);
00541 }
00542
00543
00544
00545 void Merge_TCON_Strtab (const char *buf, UINT32 size, STR_IDX_MAP& map) {
00546 merge_strtab (TCON_strtab, buf, size, map);
00547 }
00548
00549 #endif // MONGOOSE_BE
00550
00551