VariableListDeltaTracker.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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 "NativeTypes.h"
  11. #include "DS_List.h"
  12. #include "RakMemoryOverride.h"
  13. #include "BitStream.h"
  14. #ifndef __VARIABLE_LIST_DELTA_TRACKER
  15. #define __VARIABLE_LIST_DELTA_TRACKER
  16. namespace RakNet
  17. {
  18. /// Class to write a series of variables, copy the contents to memory, and return if the newly written value is different than what was last written
  19. /// Can also encode the reads, writes, and results directly to/from a bitstream
  20. class VariableListDeltaTracker
  21. {
  22. public:
  23. VariableListDeltaTracker();
  24. ~VariableListDeltaTracker();
  25. // Call before using a series of WriteVar
  26. void StartWrite(void);
  27. bool IsPastEndOfList(void) const {return nextWriteIndex>=variableList.Size();}
  28. /// Records the passed value of the variable to memory, and returns true if the value is different from the write before that (or if it is the first write)
  29. /// \pre Call StartWrite() before doing the first of a series of calls to WriteVar or other functions that call WriteVar
  30. /// \note Variables must be of the same type, written in the same order, each time
  31. template <class VarType>
  32. bool WriteVar(const VarType &varData)
  33. {
  34. RakNet::BitStream temp;
  35. temp.Write(varData);
  36. if (nextWriteIndex>=variableList.Size())
  37. {
  38. variableList.Push(VariableLastValueNode(temp.GetData(),temp.GetNumberOfBytesUsed()),_FILE_AND_LINE_);
  39. nextWriteIndex++;
  40. return true; // Different because it's new
  41. }
  42. if (temp.GetNumberOfBytesUsed()!=variableList[nextWriteIndex].byteLength)
  43. {
  44. variableList[nextWriteIndex].lastData=(char*) rakRealloc_Ex(variableList[nextWriteIndex].lastData, temp.GetNumberOfBytesUsed(),_FILE_AND_LINE_);
  45. variableList[nextWriteIndex].byteLength=temp.GetNumberOfBytesUsed();
  46. memcpy(variableList[nextWriteIndex].lastData,temp.GetData(),temp.GetNumberOfBytesUsed());
  47. nextWriteIndex++;
  48. variableList[nextWriteIndex].isDirty=false;
  49. return true; // Different because the serialized size is different
  50. }
  51. if (variableList[nextWriteIndex].isDirty==false && memcmp(temp.GetData(),variableList[nextWriteIndex].lastData, variableList[nextWriteIndex].byteLength)==0)
  52. {
  53. nextWriteIndex++;
  54. return false; // Same because not dirty and memcmp is the same
  55. }
  56. variableList[nextWriteIndex].isDirty=false;
  57. memcpy(variableList[nextWriteIndex].lastData,temp.GetData(),temp.GetNumberOfBytesUsed());
  58. nextWriteIndex++;
  59. return true; // Different because dirty or memcmp was different
  60. }
  61. /// Calls WriteVar. If the variable has changed, writes true, and writes the variable. Otherwise writes false.
  62. template <class VarType>
  63. bool WriteVarToBitstream(const VarType &varData, RakNet::BitStream *bitStream)
  64. {
  65. bool wasDifferent = WriteVar(varData);
  66. bitStream->Write(wasDifferent);
  67. if (wasDifferent)
  68. {
  69. bitStream->Write(varData);
  70. return true;
  71. }
  72. return false;
  73. }
  74. /// Calls WriteVarToBitstream(). Additionally, adds the boolean result of WriteVar() to boolean bit array
  75. template <class VarType>
  76. bool WriteVarToBitstream(const VarType &varData, RakNet::BitStream *bitStream, unsigned char *bArray, unsigned short writeOffset)
  77. {
  78. if (WriteVarToBitstream(varData,bitStream)==true)
  79. {
  80. BitSize_t numberOfBitsMod8 = writeOffset & 7;
  81. if ( numberOfBitsMod8 == 0 )
  82. bArray[ writeOffset >> 3 ] = 0x80;
  83. else
  84. bArray[ writeOffset >> 3 ] |= 0x80 >> ( numberOfBitsMod8 ); // Set the bit to 1
  85. return true;
  86. }
  87. else
  88. {
  89. if ( ( writeOffset & 7 ) == 0 )
  90. bArray[ writeOffset >> 3 ] = 0;
  91. return false;
  92. }
  93. }
  94. /// Paired with a call to WriteVarToBitstream(), will read a variable if it had changed. Otherwise the values remains the same.
  95. template <class VarType>
  96. static bool ReadVarFromBitstream(VarType &varData, RakNet::BitStream *bitStream)
  97. {
  98. bool wasWritten;
  99. if (bitStream->Read(wasWritten)==false)
  100. return false;
  101. if (wasWritten)
  102. {
  103. if (bitStream->Read(varData)==false)
  104. return false;
  105. }
  106. return wasWritten;
  107. }
  108. /// Variables flagged dirty will cause WriteVar() to return true, even if the variable had not otherwise changed
  109. /// This updates all the variables in the list, where in each index \a varsWritten is true, so will the variable at the corresponding index be flagged dirty
  110. void FlagDirtyFromBitArray(unsigned char *bArray);
  111. /// \internal
  112. struct VariableLastValueNode
  113. {
  114. VariableLastValueNode();
  115. VariableLastValueNode(const unsigned char *data, int _byteLength);
  116. ~VariableLastValueNode();
  117. char *lastData;
  118. unsigned int byteLength;
  119. bool isDirty;
  120. };
  121. protected:
  122. /// \internal
  123. DataStructures::List<VariableLastValueNode> variableList;
  124. /// \internal
  125. unsigned int nextWriteIndex;
  126. };
  127. }
  128. #endif
粤ICP备19079148号