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