//////////////////////////////////////////////////////////////////////////////////// /// /// \brief If the IsLargeDataSet method returns true, then this method is used /// to convert message payload data into a multi-packet stream /// according to rules defined by the JAUS standards documents. /// /// This method should only be overloaded if your message contains data /// larger than Header::MaxSize - Header::MinSize (e.g. image data) and you wish /// to optimize how data is written. By default, this method calls the /// WriteMessageBody method to generate a single large byte array, which is then /// broken up into a Packet::List for the transport layer. /// /// \param[out] stream Multi-packet stream containing serialized message /// following rules of large data sets. /// \param[out] streamHeaders Headers for packet in the stream. /// \param[in] maxPayloadSize This is the maximum packet size including /// payload, does not include transport, General /// Transport Header, or Message Code (USHORT). /// \param[in] transportHeader Additional transport header data to precede /// the general transport header of each packet. /// \param[in] startingSequenceNumber Sequence number to use for packets. /// \param[in] broadcastFlags Values to use to signify if message should be /// sent using any broadcast options (e.g. /// multicast). 0 = no options, 1 = local broadcast, /// 2 = global broadcast. /// /// \return FAILURE on error, otherwise number of packets written. /// //////////////////////////////////////////////////////////////////////////////////// int Message::WriteLargeDataSet(Packet::List& stream, Header::List& streamHeaders, const UShort maxPayloadSize, const Packet* transportHeader, const UShort startingSequenceNumber, const Byte broadcastFlags) const { Header header; header.mDestinationID = mDestinationID; header.mSourceID = mSourceID; header.mPriorityFlag = mPriority; header.mBroadcastFlag = broadcastFlags; stream.clear(); streamHeaders.clear(); Packet* temp = ((Packet *)(&mStreamPayload)); temp->Clear(); if(IsLargeDataSet() && WriteMessageBody(*temp) >= 0) { LargeDataSet::CreateLargeDataSet(header, mMessageCode, *temp, stream, streamHeaders, transportHeader, maxPayloadSize, startingSequenceNumber); return (int)stream.size(); } return FAILURE; }
//////////////////////////////////////////////////////////////////////////////////// /// /// \brief Tests large data set creation and merging. /// //////////////////////////////////////////////////////////////////////////////////// void TestLargeDataSets() { Packet payload; // Large data set payload. Header header; // Message header data. UShort messageCode = 50; // Random message type. Packet::List stream; // Multi-packet stream sequence. Header::List streamHeaders; // Mutli-packet stream sequence headers. unsigned int payloadSize = 60000; // Payload data size to create. header.mSourceID(50, 1, 1); header.mDestinationID(51, 1, 1); for(unsigned int i = 0; i < payloadSize/UINT_SIZE; i++) { payload.Write(i); } LargeDataSet::CreateLargeDataSet(header, messageCode, payload, stream, streamHeaders, NULL, 1437, 30); payload.Destroy(); messageCode = 0; header = Header(); LargeDataSet::MergeLargeDataSet(header, messageCode, payload, stream, NULL); unsigned int data; for(unsigned int i = 0; i < payloadSize/UINT_SIZE; i++) { payload.Read(data); if(data != i) { std::cout << "Large Data Sets Error: Data Does Not Match!\n"; return; } } std::random_shuffle(stream.begin(), stream.end()); LargeDataSet dataSet; for(unsigned int i = 0; i < (unsigned int)stream.size(); i++) { Header header; UShort messageCode; stream[i].SetReadPos(0); header.Read(stream[i]); stream[i].Read(messageCode); if(dataSet.AddPacket(header, messageCode, stream[i]) == false) { std::cout << "Large Data Sets Error: Could Not Collect Stream.\n"; } } // Now merge the data. LargeDataSet::MergeLargeDataSet(header, messageCode, payload, dataSet.mStream, NULL); for(unsigned int i = 0; i < payloadSize/UINT_SIZE; i++) { payload.Read(data); if(data != i) { std::cout << "Large Data Sets Error: Data Does Not Match!\n"; return; } } }
//////////////////////////////////////////////////////////////////////////////////// /// /// \brief If the Transport services of a component receive a multi-packet /// stream for a message, this method is used to read the contents. /// /// This method should only be overloaded if you wish to optimize the /// de-serialization of mutli-packet streams for your message (e.g. video data). /// By default, this method converts the stream to a larger continuous packet /// to be used by the ReadMessageBody method. /// /// \param[in] stream Multi-packet stream containing serialized message /// following rules of large data sets. /// \param[in] transportHeader Additional transport header data that precedes /// the general transport header of each packet. /// /// \return FAILURE on error, otherwise number of packets read. /// //////////////////////////////////////////////////////////////////////////////////// int Message::ReadLargeDataSet(const Packet::List& stream, const Packet* transportHeader) { Header header; UShort messageCode; if(LargeDataSet::MergeLargeDataSet(header, messageCode, mStreamPayload, stream, transportHeader)) { if(ReadMessageBody(mStreamPayload)) { mSourceID = header.mSourceID; mDestinationID = header.mDestinationID; mPriority = header.mPriorityFlag; return (int)stream.size(); } } return FAILURE; }