stringTable.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _STRINGTABLE_H_
  23. #define _STRINGTABLE_H_
  24. #ifndef _PLATFORM_H_
  25. #include "platform/platform.h"
  26. #endif
  27. #ifndef _PLATFORM_THREADS_MUTEX_H_
  28. #include "platform/threads/mutex.h"
  29. #endif
  30. #ifndef _DATACHUNKER_H_
  31. #include "memory/dataChunker.h"
  32. #endif
  33. //--------------------------------------
  34. /// A global table for the hashing and tracking of strings.
  35. ///
  36. /// Only one _StringTable is ever instantiated in Torque. It is accessible via the
  37. /// global variable StringTable.
  38. ///
  39. /// StringTable is used to manage strings in Torque. It performs the following tasks:
  40. /// - Ensures that only one pointer is ever used for a given string (through
  41. /// insert()).
  42. /// - Allows the lookup of a string in the table.
  43. ///
  44. /// @code
  45. /// // Adding a string to the StringTable.
  46. /// StringTableEntry mRoot;
  47. /// mRoot = StringTable->insert(root);
  48. ///
  49. /// // Looking up a string in the StringTable.
  50. /// StringTableEntry stName = StringTable->lookupn(name, len);
  51. ///
  52. /// // Comparing two strings in the StringTable (see below).
  53. /// if(mRoot == stName) Con::printf("These strings are equal!");
  54. /// @endcode
  55. ///
  56. /// <b>But why is this useful, you ask?</b> Because every string that's run through the
  57. /// StringTable is stored once and only once, every string has one and only one
  58. /// pointer mapped to it. As a pointer is an integer value (usually an unsigned int),
  59. /// so we can do several neat things:
  60. /// - StringTableEntrys can be compared directly for equality, instead of using
  61. /// the time-consuming dStrcmp() or dStricmp() function.
  62. /// - For things like object names, we can avoid storing multiple copies of the
  63. /// string containing the name. The StringTable ensures that we only ever store
  64. /// one copy.
  65. /// - When we're doing lookups by name (for instances, of resources), we can determine
  66. /// if the object is even registered in the system by looking up its name in the
  67. /// StringTable. Then, we can use the pointer as a hash key.
  68. ///
  69. /// The scripting engine and the resource manager are the primary users of the
  70. /// StringTable.
  71. ///
  72. /// @note Be aware that the StringTable NEVER DEALLOCATES memory, so be careful when you
  73. /// add strings to it. If you carelessly add many strings, you will end up wasting
  74. /// space.
  75. class _StringTable
  76. {
  77. private:
  78. /// @name Implementation details
  79. /// @{
  80. /// This is internal to the _StringTable class.
  81. struct Node
  82. {
  83. char *val;
  84. Node *next;
  85. };
  86. Node** buckets;
  87. U32 numBuckets;
  88. U32 itemCount;
  89. DataChunker mempool;
  90. Mutex mMutex;
  91. protected:
  92. static const U32 csm_stInitSize;
  93. _StringTable();
  94. ~_StringTable();
  95. /// @}
  96. public:
  97. /// Initialize StringTable.
  98. ///
  99. /// This is called at program start to initialize the StringTable global.
  100. static void create();
  101. /// Destroy the StringTable
  102. ///
  103. /// This is called at program end to destroy the StringTable global.
  104. static void destroy();
  105. /// Get a pointer from the string table, adding the string to the table
  106. /// if it was not already present.
  107. ///
  108. /// @param string String to check in the table (and add).
  109. /// @param caseSens Determines whether case matters.
  110. StringTableEntry insert(const char *string, bool caseSens = false);
  111. /// Get a pointer from the string table, adding the string to the table
  112. /// if it was not already present.
  113. ///
  114. /// @param string String to check in the table (and add).
  115. /// @param len Length of the string in bytes.
  116. /// @param caseSens Determines whether case matters.
  117. StringTableEntry insertn(const char *string, S32 len, bool caseSens = false);
  118. /// Get a pointer from the string table, NOT adding the string to the table
  119. /// if it was not already present.
  120. ///
  121. /// @param string String to check in the table (but not add).
  122. /// @param caseSens Determines whether case matters.
  123. StringTableEntry lookup(const char *string, bool caseSens = false);
  124. /// Get a pointer from the string table, NOT adding the string to the table
  125. /// if it was not already present.
  126. ///
  127. /// @param string String to check in the table (but not add).
  128. /// @param len Length of string in bytes.
  129. /// @param caseSens Determines whether case matters.
  130. StringTableEntry lookupn(const char *string, S32 len, bool caseSens = false);
  131. /// Resize the StringTable to be able to hold newSize items. This
  132. /// is called automatically by the StringTable when the table is
  133. /// full past a certain threshhold.
  134. ///
  135. /// @param newSize Number of new items to allocate space for.
  136. void resize(const U32 newSize);
  137. /// Hash a string into a U32.
  138. static U32 hashString(const char* in_pString);
  139. /// Hash a string of given length into a U32.
  140. static U32 hashStringn(const char* in_pString, S32 len);
  141. /// Empty string.
  142. static StringTableEntry EmptyString;
  143. };
  144. extern _StringTable *_gStringTable;
  145. inline _StringTable* _getStringTable()
  146. {
  147. if(_gStringTable == NULL)
  148. _StringTable::create();
  149. return _gStringTable;
  150. }
  151. #define StringTable _getStringTable()
  152. #endif //_STRINGTABLE_H_