BsStringID.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsPrerequisitesUtil.h"
  5. #include "BsSpinLock.h"
  6. namespace bs
  7. {
  8. /** @addtogroup String
  9. * @{
  10. */
  11. /**
  12. * A string identifier that provides very fast comparisons to other string identifiers. Significantly faster than
  13. * comparing raw strings.
  14. *
  15. * @note
  16. * Essentially a unique ID is generated for each string and then the ID is used for comparisons as if you were using
  17. * an integer or an enum.
  18. * @note
  19. * Thread safe.
  20. */
  21. class BS_UTILITY_EXPORT StringID
  22. {
  23. static const int HASH_TABLE_SIZE = 4096;
  24. static const int MAX_CHUNK_COUNT = 50;
  25. static const int ELEMENTS_PER_CHUNK = 256;
  26. static const int STRING_SIZE = 256;
  27. /** Helper class that performs string actions on both null terminated character arrays and standard strings. */
  28. template<class T>
  29. class StringIDUtil
  30. {
  31. public:
  32. static UINT32 size(T const& input) { return 0; }
  33. static void copy(T const& input, char* dest) { }
  34. static bool compare(T const& a, char* b) { return 0; }
  35. };
  36. /** Internal data that is shared by all instances for a specific string. */
  37. struct InternalData
  38. {
  39. UINT32 id;
  40. InternalData* next;
  41. char chars[STRING_SIZE];
  42. };
  43. /** Performs initialization of static members as soon as the library is loaded. */
  44. struct InitStatics
  45. {
  46. InitStatics();
  47. };
  48. public:
  49. StringID();
  50. StringID(const char* name)
  51. :mData(nullptr)
  52. {
  53. construct(name);
  54. }
  55. StringID(const String& name)
  56. :mData(nullptr)
  57. {
  58. construct(name);
  59. }
  60. template<int N>
  61. StringID(const char name[N])
  62. :mData(nullptr)
  63. {
  64. construct((const char*)name);
  65. }
  66. /** Compare to string ids for equality. Uses fast integer comparison. */
  67. bool operator== (const StringID& rhs) const
  68. {
  69. return mData == rhs.mData;
  70. }
  71. /** Compare to string ids for inequality. Uses fast integer comparison. */
  72. bool operator!= (const StringID& rhs) const
  73. {
  74. return mData != rhs.mData;
  75. }
  76. /** Returns true if the string id has no value assigned. */
  77. bool empty() const
  78. {
  79. return mData == nullptr;
  80. }
  81. /** Returns the null-terminated name of the string id. */
  82. const char* cstr() const
  83. {
  84. if (mData == nullptr)
  85. return nullptr;
  86. return mData->chars;
  87. }
  88. static const StringID NONE;
  89. private:
  90. /**Constructs a StringID object in a way that works for pointers to character arrays and standard strings. */
  91. template<class T>
  92. void construct(T const& name);
  93. /** Calculates a hash value for the provided null-terminated string. */
  94. template<class T>
  95. UINT32 calcHash(T const& input);
  96. /**
  97. * Allocates a new string entry and assigns it a unique ID. Optionally expands the chunks buffer if the new entry
  98. * doesn't fit.
  99. */
  100. InternalData* allocEntry();
  101. InternalData* mData;
  102. static volatile InitStatics mInitStatics;
  103. static InternalData* mStringHashTable[HASH_TABLE_SIZE];
  104. static InternalData* mChunks[MAX_CHUNK_COUNT];
  105. static UINT32 mNextId;
  106. static UINT32 mNumChunks;
  107. static SpinLock mSync;
  108. };
  109. /** @cond SPECIALIZATIONS */
  110. template<> struct RTTIPlainType <StringID>
  111. {
  112. enum { id = TID_StringID }; enum { hasDynamicSize = 1 };
  113. static void toMemory(const StringID& data, char* memory)
  114. {
  115. UINT32 size = getDynamicSize(data);
  116. UINT32 curSize = sizeof(UINT32);
  117. memcpy(memory, &size, curSize);
  118. memory += curSize;
  119. bool isEmpty = data.empty();
  120. memory = rttiWriteElem(isEmpty, memory);
  121. if (!isEmpty)
  122. {
  123. UINT32 length = (UINT32)strlen(data.cstr());
  124. memcpy(memory, data.cstr(), length * sizeof(char));
  125. }
  126. }
  127. static UINT32 fromMemory(StringID& data, char* memory)
  128. {
  129. UINT32 size;
  130. memcpy(&size, memory, sizeof(UINT32));
  131. memory += sizeof(UINT32);
  132. bool empty = false;
  133. memory = rttiReadElem(empty, memory);
  134. if (!empty)
  135. {
  136. UINT32 length = (size - sizeof(UINT32) - sizeof(bool)) / sizeof(char);
  137. char* name = (char*)bs_alloc(length + 1);
  138. memcpy(name, memory, length);
  139. name[length] = '\0';
  140. data = StringID(name);
  141. }
  142. return size;
  143. }
  144. static UINT32 getDynamicSize(const StringID& data)
  145. {
  146. UINT32 dataSize = sizeof(bool) + sizeof(UINT32);
  147. bool isEmpty = data.empty();
  148. if (!isEmpty)
  149. {
  150. UINT32 length = (UINT32)strlen(data.cstr());
  151. dataSize += length * sizeof(char);
  152. }
  153. return (UINT32)dataSize;
  154. }
  155. };
  156. /** @endcond */
  157. /** @} */
  158. }