| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- /*
- * Copyright (c) 2014, Oculus VR, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- */
- #include "NativeTypes.h"
- #include "DS_List.h"
- #include "RakMemoryOverride.h"
- #include "BitStream.h"
- #ifndef __VARIABLE_LIST_DELTA_TRACKER
- #define __VARIABLE_LIST_DELTA_TRACKER
- namespace RakNet
- {
- /// 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
- /// Can also encode the reads, writes, and results directly to/from a bitstream
- class VariableListDeltaTracker
- {
- public:
- VariableListDeltaTracker();
- ~VariableListDeltaTracker();
- // Call before using a series of WriteVar
- void StartWrite(void);
- bool IsPastEndOfList(void) const {return nextWriteIndex>=variableList.Size();}
- /// 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)
- /// \pre Call StartWrite() before doing the first of a series of calls to WriteVar or other functions that call WriteVar
- /// \note Variables must be of the same type, written in the same order, each time
- template <class VarType>
- bool WriteVar(const VarType &varData)
- {
- RakNet::BitStream temp;
- temp.Write(varData);
- if (nextWriteIndex>=variableList.Size())
- {
- variableList.Push(VariableLastValueNode(temp.GetData(),temp.GetNumberOfBytesUsed()),_FILE_AND_LINE_);
- nextWriteIndex++;
- return true; // Different because it's new
- }
- if (temp.GetNumberOfBytesUsed()!=variableList[nextWriteIndex].byteLength)
- {
- variableList[nextWriteIndex].lastData=(char*) rakRealloc_Ex(variableList[nextWriteIndex].lastData, temp.GetNumberOfBytesUsed(),_FILE_AND_LINE_);
- variableList[nextWriteIndex].byteLength=temp.GetNumberOfBytesUsed();
- memcpy(variableList[nextWriteIndex].lastData,temp.GetData(),temp.GetNumberOfBytesUsed());
- nextWriteIndex++;
- variableList[nextWriteIndex].isDirty=false;
- return true; // Different because the serialized size is different
- }
- if (variableList[nextWriteIndex].isDirty==false && memcmp(temp.GetData(),variableList[nextWriteIndex].lastData, variableList[nextWriteIndex].byteLength)==0)
- {
- nextWriteIndex++;
- return false; // Same because not dirty and memcmp is the same
- }
- variableList[nextWriteIndex].isDirty=false;
- memcpy(variableList[nextWriteIndex].lastData,temp.GetData(),temp.GetNumberOfBytesUsed());
- nextWriteIndex++;
- return true; // Different because dirty or memcmp was different
- }
- /// Calls WriteVar. If the variable has changed, writes true, and writes the variable. Otherwise writes false.
- template <class VarType>
- bool WriteVarToBitstream(const VarType &varData, RakNet::BitStream *bitStream)
- {
- bool wasDifferent = WriteVar(varData);
- bitStream->Write(wasDifferent);
- if (wasDifferent)
- {
- bitStream->Write(varData);
- return true;
- }
- return false;
- }
- /// Calls WriteVarToBitstream(). Additionally, adds the boolean result of WriteVar() to boolean bit array
- template <class VarType>
- bool WriteVarToBitstream(const VarType &varData, RakNet::BitStream *bitStream, unsigned char *bArray, unsigned short writeOffset)
- {
- if (WriteVarToBitstream(varData,bitStream)==true)
- {
- BitSize_t numberOfBitsMod8 = writeOffset & 7;
- if ( numberOfBitsMod8 == 0 )
- bArray[ writeOffset >> 3 ] = 0x80;
- else
- bArray[ writeOffset >> 3 ] |= 0x80 >> ( numberOfBitsMod8 ); // Set the bit to 1
- return true;
- }
- else
- {
- if ( ( writeOffset & 7 ) == 0 )
- bArray[ writeOffset >> 3 ] = 0;
- return false;
- }
- }
- /// Paired with a call to WriteVarToBitstream(), will read a variable if it had changed. Otherwise the values remains the same.
- template <class VarType>
- static bool ReadVarFromBitstream(VarType &varData, RakNet::BitStream *bitStream)
- {
- bool wasWritten;
- if (bitStream->Read(wasWritten)==false)
- return false;
- if (wasWritten)
- {
- if (bitStream->Read(varData)==false)
- return false;
- }
- return wasWritten;
- }
- /// Variables flagged dirty will cause WriteVar() to return true, even if the variable had not otherwise changed
- /// 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
- void FlagDirtyFromBitArray(unsigned char *bArray);
- /// \internal
- struct VariableLastValueNode
- {
- VariableLastValueNode();
- VariableLastValueNode(const unsigned char *data, int _byteLength);
- ~VariableLastValueNode();
- char *lastData;
- unsigned int byteLength;
- bool isDirty;
- };
- protected:
- /// \internal
- DataStructures::List<VariableLastValueNode> variableList;
- /// \internal
- unsigned int nextWriteIndex;
- };
- }
- #endif
|