StringTable.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #include "StringTable.h"
  11. #include <string.h>
  12. #include "RakAssert.h"
  13. #include <stdio.h>
  14. #include "BitStream.h"
  15. #include "StringCompressor.h"
  16. using namespace RakNet;
  17. StringTable* StringTable::instance=0;
  18. int StringTable::referenceCount=0;
  19. int RakNet::StrAndBoolComp( char *const &key, const StrAndBool &data )
  20. {
  21. return strcmp(key,(const char*)data.str);
  22. }
  23. StringTable::StringTable()
  24. {
  25. }
  26. StringTable::~StringTable()
  27. {
  28. unsigned i;
  29. for (i=0; i < orderedStringList.Size(); i++)
  30. {
  31. if (orderedStringList[i].b)
  32. rakFree_Ex(orderedStringList[i].str, _FILE_AND_LINE_ );
  33. }
  34. }
  35. void StringTable::AddReference(void)
  36. {
  37. if (++referenceCount==1)
  38. {
  39. instance = RakNet::OP_NEW<StringTable>( _FILE_AND_LINE_ );
  40. }
  41. }
  42. void StringTable::RemoveReference(void)
  43. {
  44. RakAssert(referenceCount > 0);
  45. if (referenceCount > 0)
  46. {
  47. if (--referenceCount==0)
  48. {
  49. RakNet::OP_DELETE(instance, _FILE_AND_LINE_);
  50. instance=0;
  51. }
  52. }
  53. }
  54. StringTable* StringTable::Instance(void)
  55. {
  56. return instance;
  57. }
  58. void StringTable::AddString(const char *str, bool copyString)
  59. {
  60. StrAndBool sab;
  61. sab.b=copyString;
  62. if (copyString)
  63. {
  64. sab.str = (char*) rakMalloc_Ex( strlen(str)+1, _FILE_AND_LINE_ );
  65. strcpy(sab.str, str);
  66. }
  67. else
  68. {
  69. sab.str=(char*)str;
  70. }
  71. // If it asserts inside here you are adding duplicate strings.
  72. orderedStringList.Insert(sab.str,sab, true, _FILE_AND_LINE_);
  73. // If this assert hits you need to increase the range of StringTableType
  74. RakAssert(orderedStringList.Size() < (StringTableType)-1);
  75. }
  76. void StringTable::EncodeString( const char *input, int maxCharsToWrite, RakNet::BitStream *output )
  77. {
  78. unsigned index;
  79. bool objectExists;
  80. // This is fast because the list is kept ordered.
  81. index=orderedStringList.GetIndexFromKey((char*)input, &objectExists);
  82. if (objectExists)
  83. {
  84. output->Write(true);
  85. output->Write((StringTableType)index);
  86. }
  87. else
  88. {
  89. LogStringNotFound(input);
  90. output->Write(false);
  91. StringCompressor::Instance()->EncodeString(input, maxCharsToWrite, output);
  92. }
  93. }
  94. bool StringTable::DecodeString( char *output, int maxCharsToWrite, RakNet::BitStream *input )
  95. {
  96. bool hasIndex=false;
  97. RakAssert(maxCharsToWrite>0);
  98. if (maxCharsToWrite==0)
  99. return false;
  100. if (!input->Read(hasIndex))
  101. return false;
  102. if (hasIndex==false)
  103. {
  104. StringCompressor::Instance()->DecodeString(output, maxCharsToWrite, input);
  105. }
  106. else
  107. {
  108. StringTableType index;
  109. if (!input->Read(index))
  110. return false;
  111. if (index >= orderedStringList.Size())
  112. {
  113. #ifdef _DEBUG
  114. // Critical error - got a string index out of range, which means AddString was called more times on the remote system than on this system.
  115. // All systems must call AddString the same number of types, with the same strings in the same order.
  116. RakAssert(0);
  117. #endif
  118. return false;
  119. }
  120. strncpy(output, orderedStringList[index].str, maxCharsToWrite);
  121. output[maxCharsToWrite-1]=0;
  122. }
  123. return true;
  124. }
  125. void StringTable::LogStringNotFound(const char *strName)
  126. {
  127. (void) strName;
  128. #ifdef _DEBUG
  129. RAKNET_DEBUG_PRINTF("Efficiency Warning! Unregistered String %s sent to StringTable.\n", strName);
  130. #endif
  131. }
粤ICP备19079148号