#include "AMFFormat_BitStream.h" // Writes an AMFValue pointer to a RakNet::BitStream template<> void RakNet::BitStream::Write(AMFValue* value) { if (value != nullptr) { AMFValueType type = value->GetValueType(); switch (type) { case AMFUndefined: { AMFUndefinedValue* v = (AMFUndefinedValue*)value; this->Write(*v); break; } case AMFNull: { AMFNullValue* v = (AMFNullValue*)value; this->Write(*v); break; } case AMFFalse: { AMFFalseValue* v = (AMFFalseValue*)value; this->Write(*v); break; } case AMFTrue: { AMFTrueValue* v = (AMFTrueValue*)value; this->Write(*v); break; } case AMFInteger: { AMFIntegerValue* v = (AMFIntegerValue*)value; this->Write(*v); break; } case AMFString: { AMFStringValue* v = (AMFStringValue*)value; this->Write(*v); break; } case AMFXMLDoc: { AMFXMLDocValue* v = (AMFXMLDocValue*)value; this->Write(*v); break; } case AMFDate: { AMFDateValue* v = (AMFDateValue*)value; this->Write(*v); break; } case AMFArray: { AMFArrayValue* v = (AMFArrayValue*)value; this->Write(*v); break; } } } } // A private function to write an value to a RakNet::BitStream void WriteUInt29(RakNet::BitStream* bs, uint32_t v) { unsigned char b4 = (unsigned char)v; if (v < 0x00200000) { b4 = b4 & 0x7F; if (v > 0x7F) { unsigned char b3; v = v >> 7; b3 = ((unsigned char)(v)) | 0x80; if (v > 0x7F) { unsigned char b2; v = v >> 7; b2 = ((unsigned char)(v)) | 0x80; bs->Write(b2); } bs->Write(b3); } } else { unsigned char b1; unsigned char b2; unsigned char b3; v = v >> 8; b3 = ((unsigned char)(v)) | 0x80; v = v >> 7; b2 = ((unsigned char)(v)) | 0x80; v = v >> 7; b1 = ((unsigned char)(v)) | 0x80; bs->Write(b1); bs->Write(b2); bs->Write(b3); } bs->Write(b4); } // Writes a flag number to a RakNet::BitStream void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) { v = (v << 1) | 0x01; WriteUInt29(bs, v); } // Writes an AMFString to a RakNet::BitStream void WriteAMFString(RakNet::BitStream* bs, const std::string& str) { WriteFlagNumber(bs, (uint32_t)str.size()); bs->Write(str.c_str(), (uint32_t)str.size()); } // Writes an AMF U16 to a RakNet::BitStream void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) { unsigned char b2; b2 = (unsigned char)value; value = value >> 8; bs->Write((unsigned char)value); bs->Write(b2); } // Writes an AMF U32 to RakNet::BitStream void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) { unsigned char b2; unsigned char b3; unsigned char b4; b4 = (unsigned char)value; value = value >> 8; b3 = (unsigned char)value; value = value >> 8; b2 = (unsigned char)value; value = value >> 8; bs->Write((unsigned char)value); bs->Write(b2); bs->Write(b3); bs->Write(b4); } // Writes an AMF U64 to RakNet::BitStream void WriteAMFU64(RakNet::BitStream* bs, uint64_t value) { unsigned char b2; unsigned char b3; unsigned char b4; unsigned char b5; unsigned char b6; unsigned char b7; unsigned char b8; b8 = (unsigned char)value; value = value >> 8; b7 = (unsigned char)value; value = value >> 8; b6 = (unsigned char)value; value = value >> 8; b5 = (unsigned char)value; value = value >> 8; b4 = (unsigned char)value; value = value >> 8; b3 = (unsigned char)value; value = value >> 8; b2 = (unsigned char)value; value = value >> 8; bs->Write((unsigned char)value); bs->Write(b2); bs->Write(b3); bs->Write(b4); bs->Write(b5); bs->Write(b6); bs->Write(b7); bs->Write(b8); } // Writes an AMFUndefinedValue to BitStream template<> void RakNet::BitStream::Write(AMFUndefinedValue value) { this->Write(AMFUndefined); } // Writes an AMFNullValue to BitStream template<> void RakNet::BitStream::Write(AMFNullValue value) { this->Write(AMFNull); } // Writes an AMFFalseValue to BitStream template<> void RakNet::BitStream::Write(AMFFalseValue value) { this->Write(AMFFalse); } // Writes an AMFTrueValue to BitStream template<> void RakNet::BitStream::Write(AMFTrueValue value) { this->Write(AMFTrue); } // Writes an AMFIntegerValue to BitStream template<> void RakNet::BitStream::Write(AMFIntegerValue value) { this->Write(AMFInteger); WriteUInt29(this, value.GetIntegerValue()); } // Writes an AMFDoubleValue to BitStream template<> void RakNet::BitStream::Write(AMFDoubleValue value) { this->Write(AMFDouble); double d = value.GetDoubleValue(); WriteAMFU64(this, *((unsigned long long*)&d)); } // Writes an AMFStringValue to BitStream template<> void RakNet::BitStream::Write(AMFStringValue value) { this->Write(AMFString); std::string v = value.GetStringValue(); WriteAMFString(this, v); } // Writes an AMFXMLDocValue to BitStream template<> void RakNet::BitStream::Write(AMFXMLDocValue value) { this->Write(AMFXMLDoc); std::string v = value.GetXMLDocValue(); WriteAMFString(this, v); } // Writes an AMFDateValue to BitStream template<> void RakNet::BitStream::Write(AMFDateValue value) { this->Write(AMFDate); uint64_t date = value.GetDateValue(); WriteAMFU64(this, date); } // Writes an AMFArrayValue to BitStream template<> void RakNet::BitStream::Write(AMFArrayValue value) { this->Write(AMFArray); uint32_t denseSize = value.GetDenseValueSize(); WriteFlagNumber(this, denseSize); _AMFArrayMap_::iterator it = value.GetAssociativeIteratorValueBegin(); _AMFArrayMap_::iterator end = value.GetAssociativeIteratorValueEnd(); while (it != end) { WriteAMFString(this, it->first); this->Write(it->second); it++; } this->Write(AMFNull); if (denseSize > 0) { _AMFArrayList_::iterator it2 = value.GetDenseIteratorBegin(); _AMFArrayList_::iterator end2 = value.GetDenseIteratorEnd(); while (it2 != end2) { this->Write(*it2); it2++; } } }