llstringtable.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /**
  2. * @file llstringtable.cpp
  3. * @brief The LLStringTable class provides a _fast_ method for finding
  4. * unique copies of strings.
  5. *
  6. * $LicenseInfo:firstyear=2001&license=viewergpl$
  7. *
  8. * Copyright (c) 2001-2009, Linden Research, Inc.
  9. *
  10. * Second Life Viewer Source Code
  11. * The source code in this file ("Source Code") is provided by Linden Lab
  12. * to you under the terms of the GNU General Public License, version 2.0
  13. * ("GPL"), unless you have obtained a separate licensing agreement
  14. * ("Other License"), formally executed by you and Linden Lab. Terms of
  15. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17. *
  18. * There are special exceptions to the terms and conditions of the GPL as
  19. * it is applied to this Source Code. View the full text of the exception
  20. * in the file doc/FLOSS-exception.txt in this software distribution, or
  21. * online at
  22. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23. *
  24. * By copying, modifying or distributing this software, you acknowledge
  25. * that you have read and understood your obligations described above,
  26. * and agree to abide by those obligations.
  27. *
  28. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30. * COMPLETENESS OR PERFORMANCE.
  31. * $/LicenseInfo$
  32. */
  33. #include "linden_common.h"
  34. #include "llstringtable.h"
  35. LLStringTable gStringTable(32768);
  36. // Helper function
  37. static U32 make_hash(const char* str, U32 max_entries)
  38. {
  39. U32 retval = 0;
  40. if (*str)
  41. {
  42. retval = digest64to32(HBXXH64::digest(str));
  43. }
  44. // max_entries is guaranteed to be a power of 2
  45. return retval & (max_entries - 1);
  46. }
  47. ///////////////////////////////////////////////////////////////////////////////
  48. // LLStringTableEntry class
  49. ///////////////////////////////////////////////////////////////////////////////
  50. LLStringTableEntry::LLStringTableEntry(const char* str)
  51. : mString(NULL),
  52. mCount(1)
  53. {
  54. // Copy string
  55. U32 length = (U32)strlen(str) + 1;
  56. length = llmin(length, MAX_STRINGS_LENGTH);
  57. mString = new char[length];
  58. strncpy(mString, str, length);
  59. mString[length - 1] = 0;
  60. }
  61. LLStringTableEntry::~LLStringTableEntry()
  62. {
  63. if (mString)
  64. {
  65. delete[] mString;
  66. mString = NULL;
  67. }
  68. mCount = 0;
  69. }
  70. ///////////////////////////////////////////////////////////////////////////////
  71. // LLStringTable class
  72. ///////////////////////////////////////////////////////////////////////////////
  73. LLStringTable::LLStringTable(S32 tablesize)
  74. : mUniqueEntries(0)
  75. {
  76. if (tablesize <= 0)
  77. {
  78. tablesize = 4096; // Some arbitrary default
  79. }
  80. // Make sure tablesize is power of 2
  81. for (S32 i = 31; i > 0; --i)
  82. {
  83. if (tablesize & (1 << i))
  84. {
  85. if (tablesize >= 3 << (i - 1))
  86. {
  87. tablesize = 1 << (i + 1);
  88. }
  89. else
  90. {
  91. tablesize = 1 << i;
  92. }
  93. break;
  94. }
  95. }
  96. mMaxEntries = tablesize;
  97. // Allocate strings
  98. mStringList = new string_list_ptr_t[mMaxEntries];
  99. // Clear strings
  100. for (U32 i = 0; i < mMaxEntries; ++i)
  101. {
  102. mStringList[i] = NULL;
  103. }
  104. }
  105. LLStringTable::~LLStringTable()
  106. {
  107. if (mStringList)
  108. {
  109. for (U32 i = 0; i < mMaxEntries; ++i)
  110. {
  111. if (mStringList[i])
  112. {
  113. for (string_list_t::iterator iter = mStringList[i]->begin(),
  114. end = mStringList[i]->end();
  115. iter != end; ++iter)
  116. {
  117. LLStringTableEntry* entry = *iter;
  118. if (entry)
  119. {
  120. delete entry;
  121. }
  122. }
  123. delete mStringList[i];
  124. }
  125. }
  126. delete[] mStringList;
  127. mStringList = NULL;
  128. }
  129. }
  130. LLStringTableEntry* LLStringTable::checkStringEntry(const char* str)
  131. {
  132. if (str)
  133. {
  134. U32 hash_value = make_hash(str, mMaxEntries);
  135. string_list_t* strlist = mStringList[hash_value];
  136. if (strlist)
  137. {
  138. for (string_list_t::iterator iter = strlist->begin(),
  139. end = strlist->end();
  140. iter != end; ++iter)
  141. {
  142. LLStringTableEntry* entry = *iter;
  143. char* ret_val = entry->mString;
  144. if (!strncmp(ret_val, str, MAX_STRINGS_LENGTH))
  145. {
  146. return entry;
  147. }
  148. }
  149. }
  150. }
  151. return NULL;
  152. }
  153. LLStringTableEntry* LLStringTable::addStringEntry(const char* str)
  154. {
  155. if (!str)
  156. {
  157. return NULL;
  158. }
  159. U32 hash_value = make_hash(str, mMaxEntries);
  160. string_list_t* strlist = mStringList[hash_value];
  161. if (strlist)
  162. {
  163. for (string_list_t::iterator iter = strlist->begin(),
  164. end = strlist->end();
  165. iter != end; ++iter)
  166. {
  167. LLStringTableEntry* entry = *iter;
  168. char* entry_str = entry->mString;
  169. if (!strncmp(entry_str, str, MAX_STRINGS_LENGTH))
  170. {
  171. entry->incCount();
  172. return entry;
  173. }
  174. }
  175. }
  176. else
  177. {
  178. strlist = new string_list_t;
  179. mStringList[hash_value] = strlist;
  180. }
  181. // Not found, so add !
  182. if (++mUniqueEntries > mMaxEntries)
  183. {
  184. llerrs << "String table too small to store a new entry: "
  185. << mMaxEntries << " stored." << llendl;
  186. }
  187. LLStringTableEntry* newentry = new LLStringTableEntry(str);
  188. strlist->push_front(newentry);
  189. LL_DEBUGS("StringTable") << mUniqueEntries << "/" << mMaxEntries
  190. << " unique entries." << LL_ENDL;
  191. return newentry;
  192. }
  193. void LLStringTable::removeString(const char* str)
  194. {
  195. if (!str)
  196. {
  197. return;
  198. }
  199. U32 hash_value = make_hash(str, mMaxEntries);
  200. string_list_t* strlist = mStringList[hash_value];
  201. if (!strlist)
  202. {
  203. return;
  204. }
  205. for (string_list_t::iterator iter = strlist->begin(), end = strlist->end();
  206. iter != end; ++iter)
  207. {
  208. LLStringTableEntry* entry = *iter;
  209. char* entry_str = entry->mString;
  210. if (!strncmp(entry_str, str, MAX_STRINGS_LENGTH))
  211. {
  212. if (!entry->decCount())
  213. {
  214. if (!mUniqueEntries)
  215. {
  216. llerrs << "Trying to remove too many strings !" << llendl;
  217. }
  218. --mUniqueEntries;
  219. strlist->remove(entry);
  220. delete entry;
  221. }
  222. return;
  223. }
  224. }
  225. }
  226. ///////////////////////////////////////////////////////////////////////////////
  227. // LLStdStringTable class
  228. ///////////////////////////////////////////////////////////////////////////////
  229. LLStdStringTable::LLStdStringTable(S32 tablesize)
  230. {
  231. if (tablesize <= 0)
  232. {
  233. tablesize = 256; // Default
  234. }
  235. else
  236. {
  237. // Make sure tablesize is power of 2
  238. S32 initial_size = tablesize;
  239. tablesize = 2;
  240. while (tablesize < initial_size)
  241. {
  242. tablesize *= 2;
  243. }
  244. }
  245. mTableSize = (U32)tablesize;
  246. mStringList = new string_set_t[tablesize];
  247. }
  248. void LLStdStringTable::cleanup()
  249. {
  250. // Remove strings
  251. for (U32 i = 0; i < mTableSize; ++i)
  252. {
  253. string_set_t& stringset = mStringList[i];
  254. for (string_set_t::iterator iter = stringset.begin(),
  255. end = stringset.end();
  256. iter != end; ++iter)
  257. {
  258. delete *iter;
  259. }
  260. stringset.clear();
  261. }
  262. }