stringTable.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 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 _DATACHUNKER_H_
  28. #include "core/dataChunker.h"
  29. #endif
  30. //--------------------------------------
  31. /// A global table for the hashing and tracking of strings.
  32. ///
  33. /// Only one _StringTable is ever instantiated in Torque. It is accessible via the
  34. /// global variable StringTable.
  35. ///
  36. /// StringTable is used to manage strings in Torque. It performs the following tasks:
  37. /// - Ensures that only one pointer is ever used for a given string (through
  38. /// insert()).
  39. /// - Allows the lookup of a string in the table.
  40. ///
  41. /// @code
  42. /// // Adding a string to the StringTable.
  43. /// StringTableEntry mRoot;
  44. /// mRoot = StringTable->insert(root);
  45. ///
  46. /// // Looking up a string in the StringTable.
  47. /// StringTableEntry stName = StringTable->lookupn(name, len);
  48. ///
  49. /// // Comparing two strings in the StringTable (see below).
  50. /// if(mRoot == stName) Con::printf("These strings are equal!");
  51. /// @endcode
  52. ///
  53. /// <b>But why is this useful, you ask?</b> Because every string that's run through the
  54. /// StringTable is stored once and only once, every string has one and only one
  55. /// pointer mapped to it. As a pointer is an integer value (usually an unsigned int),
  56. /// so we can do several neat things:
  57. /// - StringTableEntrys can be compared directly for equality, instead of using
  58. /// the time-consuming String::compare() or dStricmp() function.
  59. /// - For things like object names, we can avoid storing multiple copies of the
  60. /// string containing the name. The StringTable ensures that we only ever store
  61. /// one copy.
  62. /// - When we're doing lookups by name (for instances, of resources), we can determine
  63. /// if the object is even registered in the system by looking up its name in the
  64. /// StringTable. Then, we can use the pointer as a hash key.
  65. ///
  66. /// The scripting engine and the resource manager are the primary users of the
  67. /// StringTable.
  68. ///
  69. /// @note Be aware that the StringTable NEVER DEALLOCATES memory, so be careful when you
  70. /// add strings to it. If you carelessly add many strings, you will end up wasting
  71. /// space.
  72. class _StringTable
  73. {
  74. private:
  75. /// @name Implementation details
  76. /// @{
  77. /// This is internal to the _StringTable class.
  78. struct Node
  79. {
  80. char *val;
  81. Node *next;
  82. };
  83. Node** buckets;
  84. U32 numBuckets;
  85. U32 itemCount;
  86. DataChunker mempool;
  87. StringTableEntry _EmptyString;
  88. protected:
  89. static const U32 csm_stInitSize;
  90. _StringTable();
  91. ~_StringTable();
  92. /// @}
  93. public:
  94. /// Initialize StringTable.
  95. ///
  96. /// This is called at program start to initialize the StringTable global.
  97. static void create();
  98. /// Destroy the StringTable
  99. ///
  100. /// This is called at program end to destroy the StringTable global.
  101. static void destroy();
  102. /// Get a pointer from the string table, adding the string to the table
  103. /// if it was not already present.
  104. ///
  105. /// @param string String to check in the table (and add).
  106. /// @param caseSens Determines whether case matters.
  107. StringTableEntry insert(const char *string, bool caseSens = false);
  108. /// Get a pointer from the string table, adding the string to the table
  109. /// if it was not already present.
  110. ///
  111. /// @param string String to check in the table (and add).
  112. /// @param len Length of the string in bytes.
  113. /// @param caseSens Determines whether case matters.
  114. StringTableEntry insertn(const char *string, S32 len, bool caseSens = false);
  115. /// Get a pointer from the string table, NOT adding the string to the table
  116. /// if it was not already present.
  117. ///
  118. /// @param string String to check in the table (but not add).
  119. /// @param caseSens Determines whether case matters.
  120. StringTableEntry lookup(const char *string, bool caseSens = false);
  121. /// Get a pointer from the string table, NOT adding the string to the table
  122. /// if it was not already present.
  123. ///
  124. /// @param string String to check in the table (but not add).
  125. /// @param len Length of string in bytes.
  126. /// @param caseSens Determines whether case matters.
  127. StringTableEntry lookupn(const char *string, S32 len, bool caseSens = false);
  128. /// Resize the StringTable to be able to hold newSize items. This
  129. /// is called automatically by the StringTable when the table is
  130. /// full past a certain threshhold.
  131. ///
  132. /// @param newSize Number of new items to allocate space for.
  133. void resize(const U32 newSize);
  134. /// Hash a string into a U32.
  135. static U32 hashString(const char* in_pString);
  136. /// Hash a string of given length into a U32.
  137. static U32 hashStringn(const char* in_pString, S32 len);
  138. /// Represents a zero length string.
  139. StringTableEntry EmptyString() const { return _EmptyString; }
  140. };
  141. extern _StringTable *_gStringTable;
  142. inline _StringTable* _getStringTable()
  143. {
  144. if(_gStringTable == NULL)
  145. _StringTable::create();
  146. return _gStringTable;
  147. }
  148. #define StringTable _getStringTable()
  149. #endif //_STRINGTABLE_H_