00001
00033 #ifndef LL_STRING_TABLE_H
00034 #define LL_STRING_TABLE_H
00035
00036 #include "lldefs.h"
00037 #include "llformat.h"
00038 #include "llstl.h"
00039 #include <list>
00040 #include <set>
00041
00042 #if LL_WINDOWS
00043 # if (_MSC_VER >= 1300 && _MSC_VER < 1400)
00044 # define STRING_TABLE_HASH_MAP 1
00045 # endif
00046 #else
00047
00048 #endif
00049
00050 #if LL_WINDOWS
00051 #include <hash_map>
00052 #else
00053 #include <ext/hash_map>
00054 #endif
00055
00056 const U32 MAX_STRINGS_LENGTH = 256;
00057
00058 class LLStringTableEntry
00059 {
00060 public:
00061 LLStringTableEntry(const char *str)
00062 : mString(NULL), mCount(1)
00063 {
00064
00065 U32 length = (U32)strlen(str) + 1;
00066 length = llmin(length, MAX_STRINGS_LENGTH);
00067 mString = new char[length];
00068 strncpy(mString, str, length);
00069 mString[length - 1] = 0;
00070 }
00071 ~LLStringTableEntry()
00072 {
00073 delete [] mString;
00074 mCount = 0;
00075 }
00076 void incCount() { mCount++; }
00077 BOOL decCount() { return --mCount; }
00078
00079 char *mString;
00080 S32 mCount;
00081 };
00082
00083 class LLStringTable
00084 {
00085 public:
00086 LLStringTable(int tablesize);
00087 ~LLStringTable();
00088
00089 char *checkString(const char *str);
00090 char *checkString(const std::string& str);
00091 LLStringTableEntry *checkStringEntry(const char *str);
00092 LLStringTableEntry *checkStringEntry(const std::string& str);
00093
00094 char *addString(const char *str);
00095 char *addString(const std::string& str);
00096 LLStringTableEntry *addStringEntry(const char *str);
00097 LLStringTableEntry *addStringEntry(const std::string& str);
00098 void removeString(const char *str);
00099
00100 S32 mMaxEntries;
00101 S32 mUniqueEntries;
00102
00103 #if STRING_TABLE_HASH_MAP
00104 #if LL_WINDOWS
00105 typedef std::hash_multimap<U32, LLStringTableEntry *> string_hash_t;
00106 #else
00107 typedef __gnu_cxx::hash_multimap<U32, LLStringTableEntry *> string_hash_t;
00108 #endif
00109 string_hash_t mStringHash;
00110 #else
00111 typedef std::list<LLStringTableEntry *> string_list_t;
00112 typedef string_list_t * string_list_ptr_t;
00113 string_list_ptr_t *mStringList;
00114 #endif
00115 };
00116
00117 extern LLStringTable gStringTable;
00118
00119
00120
00121
00122
00123
00124
00125 typedef const std::string* LLStdStringHandle;
00126
00127 class LLStdStringTable
00128 {
00129 public:
00130 LLStdStringTable(S32 tablesize = 0)
00131 {
00132 if (tablesize == 0)
00133 {
00134 tablesize = 256;
00135 }
00136
00137 for (S32 i = 31; i>0; i--)
00138 {
00139 if (tablesize & (1<<i))
00140 {
00141 if (tablesize >= (3<<(i-1)))
00142 tablesize = (1<<(i+1));
00143 else
00144 tablesize = (1<<i);
00145 break;
00146 }
00147 }
00148 mTableSize = tablesize;
00149 mStringList = new string_set_t[tablesize];
00150 }
00151 ~LLStdStringTable()
00152 {
00153 cleanup();
00154 delete[] mStringList;
00155 }
00156 void cleanup()
00157 {
00158
00159 for (S32 i = 0; i<mTableSize; i++)
00160 {
00161 string_set_t& stringset = mStringList[i];
00162 for (string_set_t::iterator iter = stringset.begin(); iter != stringset.end(); iter++)
00163 {
00164 delete *iter;
00165 }
00166 stringset.clear();
00167 }
00168 }
00169
00170 LLStdStringHandle lookup(const std::string& s)
00171 {
00172 U32 hashval = makehash(s);
00173 return lookup(hashval, s);
00174 }
00175
00176 LLStdStringHandle checkString(const std::string& s)
00177 {
00178 U32 hashval = makehash(s);
00179 return lookup(hashval, s);
00180 }
00181
00182 LLStdStringHandle insert(const std::string& s)
00183 {
00184 U32 hashval = makehash(s);
00185 LLStdStringHandle result = lookup(hashval, s);
00186 if (result == NULL)
00187 {
00188 result = new std::string(s);
00189 mStringList[hashval].insert(result);
00190 }
00191 return result;
00192 }
00193 LLStdStringHandle addString(const std::string& s)
00194 {
00195 return insert(s);
00196 }
00197
00198 private:
00199 U32 makehash(const std::string& s)
00200 {
00201 S32 len = (S32)s.size();
00202 const char* c = s.c_str();
00203 U32 hashval = 0;
00204 for (S32 i=0; i<len; i++)
00205 {
00206 hashval = ((hashval<<5) + hashval) + *c++;
00207 }
00208 return hashval & (mTableSize-1);
00209 }
00210 LLStdStringHandle lookup(U32 hashval, const std::string& s)
00211 {
00212 string_set_t& stringset = mStringList[hashval];
00213 LLStdStringHandle handle = &s;
00214 string_set_t::iterator iter = stringset.find(handle);
00215 if (iter != stringset.end())
00216 {
00217 return *iter;
00218 }
00219 else
00220 {
00221 return NULL;
00222 }
00223 }
00224
00225 private:
00226 S32 mTableSize;
00227 typedef std::set<LLStdStringHandle, compare_pointer_contents<std::string> > string_set_t;
00228 string_set_t* mStringList;
00229 };
00230
00231
00232 #endif