mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-30 18:00:06 +00:00 
			
		
		
		
	Parse Clutter Filter Map (Message 15)
This commit is contained in:
		
							parent
							
								
									f36d57b71d
								
							
						
					
					
						commit
						3ab4ec4b9b
					
				
					 15 changed files with 682 additions and 22 deletions
				
			
		
							
								
								
									
										19
									
								
								wxdata/source/scwx/util/vectorbuf.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								wxdata/source/scwx/util/vectorbuf.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| #include <scwx/util/vectorbuf.hpp> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace util | ||||
| { | ||||
| 
 | ||||
| vectorbuf::vectorbuf(std::vector<char>& v) : v_(v) | ||||
| { | ||||
|    update_read_pointers(0); | ||||
| } | ||||
| 
 | ||||
| void vectorbuf::update_read_pointers(size_t size) | ||||
| { | ||||
|    setg(v_.data(), v_.data(), v_.data() + size); | ||||
| } | ||||
| 
 | ||||
| } // namespace util
 | ||||
| } // namespace scwx
 | ||||
|  | @ -1,5 +1,5 @@ | |||
| #include <scwx/wsr88d/ar2v_file.hpp> | ||||
| #include <scwx/wsr88d/rda/message_header.hpp> | ||||
| #include <scwx/wsr88d/rda/message_factory.hpp> | ||||
| #include <scwx/util/rangebuf.hpp> | ||||
| 
 | ||||
| #include <fstream> | ||||
|  | @ -54,7 +54,7 @@ Ar2vFile::Ar2vFile() : p(std::make_unique<Ar2vFileImpl>()) {} | |||
| Ar2vFile::~Ar2vFile() = default; | ||||
| 
 | ||||
| Ar2vFile::Ar2vFile(Ar2vFile&&) noexcept = default; | ||||
| Ar2vFile& Ar2vFile::operator=(Ar2vFile&&) = default; | ||||
| Ar2vFile& Ar2vFile::operator=(Ar2vFile&&) noexcept = default; | ||||
| 
 | ||||
| bool Ar2vFile::LoadFile(const std::string& filename) | ||||
| { | ||||
|  | @ -112,6 +112,8 @@ bool Ar2vFile::LoadFile(const std::string& filename) | |||
| 
 | ||||
| void Ar2vFileImpl::LoadLDMRecords(std::ifstream& f) | ||||
| { | ||||
|    BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Loading LDM Records"; | ||||
| 
 | ||||
|    numRecords_ = 0; | ||||
| 
 | ||||
|    while (f.peek() != EOF) | ||||
|  | @ -163,6 +165,8 @@ void Ar2vFileImpl::LoadLDMRecords(std::ifstream& f) | |||
| 
 | ||||
| void Ar2vFileImpl::ParseLDMRecords() | ||||
| { | ||||
|    BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Parsing LDM Records"; | ||||
| 
 | ||||
|    size_t count = 0; | ||||
| 
 | ||||
|    for (auto it = rawRecords_.begin(); it != rawRecords_.end(); it++) | ||||
|  | @ -177,18 +181,13 @@ void Ar2vFileImpl::ParseLDMRecords() | |||
| 
 | ||||
|       while (!ss.eof()) | ||||
|       { | ||||
|          // TODO: Parse message, not just header
 | ||||
|          rda::MessageHeader header; | ||||
|          if (!header.Parse(ss)) | ||||
|          rda::MessageInfo msgInfo = rda::MessageFactory::Create(ss); | ||||
|          if (!msgInfo.headerValid) | ||||
|          { | ||||
|             // Invalid header
 | ||||
|             // Invalid message
 | ||||
|             break; | ||||
|          } | ||||
| 
 | ||||
|          // Seek to the end of the current message
 | ||||
|          ss.seekg(header.message_size() * 2 - rda::MessageHeader::SIZE, | ||||
|                   std::ios_base::cur); | ||||
| 
 | ||||
|          off_t    offset   = 0; | ||||
|          uint16_t nextSize = 0u; | ||||
|          do | ||||
|  |  | |||
							
								
								
									
										234
									
								
								wxdata/source/scwx/wsr88d/rda/clutter_filter_map.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								wxdata/source/scwx/wsr88d/rda/clutter_filter_map.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,234 @@ | |||
| #include <scwx/wsr88d/rda/clutter_filter_map.hpp> | ||||
| 
 | ||||
| #include <istream> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include <boost/log/trivial.hpp> | ||||
| 
 | ||||
| #ifdef WIN32 | ||||
| #   include <WinSock2.h> | ||||
| #else | ||||
| #   include <arpa/inet.h> | ||||
| #endif | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace wsr88d | ||||
| { | ||||
| namespace rda | ||||
| { | ||||
| 
 | ||||
| static const std::string logPrefix_ = | ||||
|    "[scwx::wsr88d::rda::clutter_filter_map] "; | ||||
| 
 | ||||
| struct RangeZone | ||||
| { | ||||
|    uint16_t opCode; | ||||
|    uint16_t endRange; | ||||
| }; | ||||
| 
 | ||||
| class ClutterFilterMapImpl | ||||
| { | ||||
| public: | ||||
|    explicit ClutterFilterMapImpl() : | ||||
|        mapGenerationDate_(), mapGenerationTime_(), rangeZones_() {}; | ||||
|    ~ClutterFilterMapImpl() = default; | ||||
| 
 | ||||
|    uint16_t mapGenerationDate_; | ||||
|    uint16_t mapGenerationTime_; | ||||
| 
 | ||||
|    std::vector<std::vector<std::vector<RangeZone>>> rangeZones_; | ||||
| }; | ||||
| 
 | ||||
| ClutterFilterMap::ClutterFilterMap() : | ||||
|     Message(), p(std::make_unique<ClutterFilterMapImpl>()) | ||||
| { | ||||
| } | ||||
| ClutterFilterMap::~ClutterFilterMap() = default; | ||||
| 
 | ||||
| ClutterFilterMap::ClutterFilterMap(ClutterFilterMap&&) noexcept = default; | ||||
| ClutterFilterMap& | ||||
| ClutterFilterMap::operator=(ClutterFilterMap&&) noexcept = default; | ||||
| 
 | ||||
| uint16_t ClutterFilterMap::map_generation_date() const | ||||
| { | ||||
|    return p->mapGenerationDate_; | ||||
| } | ||||
| 
 | ||||
| uint16_t ClutterFilterMap::map_generation_time() const | ||||
| { | ||||
|    return p->mapGenerationTime_; | ||||
| } | ||||
| 
 | ||||
| uint16_t ClutterFilterMap::number_of_elevation_segments() const | ||||
| { | ||||
|    return static_cast<uint16_t>(p->rangeZones_.size()); | ||||
| } | ||||
| 
 | ||||
| uint16_t ClutterFilterMap::number_of_range_zones(uint16_t e, uint16_t a) const | ||||
| { | ||||
|    return static_cast<uint16_t>(p->rangeZones_[e][a].size()); | ||||
| } | ||||
| 
 | ||||
| uint16_t ClutterFilterMap::op_code(uint16_t e, uint16_t a, uint16_t z) const | ||||
| { | ||||
|    return p->rangeZones_[e][a][z].opCode; | ||||
| } | ||||
| 
 | ||||
| uint16_t ClutterFilterMap::end_range(uint16_t e, uint16_t a, uint16_t z) const | ||||
| { | ||||
|    return p->rangeZones_[e][a][z].endRange; | ||||
| } | ||||
| 
 | ||||
| bool ClutterFilterMap::Parse(std::istream& is) | ||||
| { | ||||
|    BOOST_LOG_TRIVIAL(debug) | ||||
|       << logPrefix_ << "Parsing Clutter Filter Map (Message Type 15)"; | ||||
| 
 | ||||
|    bool     messageValid         = true; | ||||
|    size_t   bytesRead            = 0; | ||||
|    uint16_t numElevationSegments = 0; | ||||
| 
 | ||||
|    is.read(reinterpret_cast<char*>(&p->mapGenerationDate_), 2); | ||||
|    is.read(reinterpret_cast<char*>(&p->mapGenerationTime_), 2); | ||||
|    is.read(reinterpret_cast<char*>(&numElevationSegments), 2); | ||||
|    bytesRead += 6; | ||||
| 
 | ||||
|    p->mapGenerationDate_ = htons(p->mapGenerationDate_); | ||||
|    p->mapGenerationTime_ = htons(p->mapGenerationTime_); | ||||
|    numElevationSegments  = htons(numElevationSegments); | ||||
| 
 | ||||
|    if (is.eof()) | ||||
|    { | ||||
|       BOOST_LOG_TRIVIAL(warning) << logPrefix_ << "Reached end of file (1)"; | ||||
|       messageValid = false; | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       if (p->mapGenerationDate_ < 1) | ||||
|       { | ||||
|          BOOST_LOG_TRIVIAL(warning) | ||||
|             << logPrefix_ << "Invalid date: " << p->mapGenerationDate_; | ||||
|          messageValid = false; | ||||
|       } | ||||
|       if (p->mapGenerationTime_ > 1440) | ||||
|       { | ||||
|          BOOST_LOG_TRIVIAL(warning) | ||||
|             << logPrefix_ << "Invalid time: " << p->mapGenerationTime_; | ||||
|          messageValid = false; | ||||
|       } | ||||
|       if (numElevationSegments < 1 || numElevationSegments > 5) | ||||
|       { | ||||
|          BOOST_LOG_TRIVIAL(warning) | ||||
|             << logPrefix_ | ||||
|             << "Invalid number of elevation segments: " << numElevationSegments; | ||||
|          messageValid = false; | ||||
|       } | ||||
|    } | ||||
| 
 | ||||
|    if (!messageValid) | ||||
|    { | ||||
|       numElevationSegments = 0; | ||||
|    } | ||||
| 
 | ||||
|    p->rangeZones_.resize(numElevationSegments); | ||||
| 
 | ||||
|    for (uint16_t e = 0; e < numElevationSegments && messageValid; e++) | ||||
|    { | ||||
|       p->rangeZones_[e].resize(NUM_AZIMUTH_SEGMENTS); | ||||
| 
 | ||||
|       for (uint16_t a = 0; a < NUM_AZIMUTH_SEGMENTS && messageValid; a++) | ||||
|       { | ||||
|          uint16_t numRangeZones; | ||||
|          is.read(reinterpret_cast<char*>(&numRangeZones), 2); | ||||
|          bytesRead += 2; | ||||
| 
 | ||||
|          numRangeZones = htons(numRangeZones); | ||||
| 
 | ||||
|          if (is.eof()) | ||||
|          { | ||||
|             BOOST_LOG_TRIVIAL(warning) | ||||
|                << logPrefix_ << "Reached end of file (2)"; | ||||
|             messageValid = false; | ||||
|          } | ||||
|          else | ||||
|          { | ||||
|             if (numRangeZones < 1 || numRangeZones > 20) | ||||
|             { | ||||
|                BOOST_LOG_TRIVIAL(warning) | ||||
|                   << logPrefix_ | ||||
|                   << "Invalid number of range zones: " << numRangeZones; | ||||
|                messageValid = false; | ||||
|             } | ||||
|          } | ||||
| 
 | ||||
|          if (!messageValid) | ||||
|          { | ||||
|             break; | ||||
|          } | ||||
| 
 | ||||
|          p->rangeZones_[e][a].resize(numRangeZones); | ||||
| 
 | ||||
|          for (uint16_t z = 0; z < numRangeZones && messageValid; z++) | ||||
|          { | ||||
|             RangeZone& zone = p->rangeZones_[e][a][z]; | ||||
| 
 | ||||
|             is.read(reinterpret_cast<char*>(&zone.opCode), 2); | ||||
|             is.read(reinterpret_cast<char*>(&zone.endRange), 2); | ||||
|             bytesRead += 4; | ||||
| 
 | ||||
|             zone.opCode   = htons(zone.opCode); | ||||
|             zone.endRange = htons(zone.endRange); | ||||
| 
 | ||||
|             if (is.eof()) | ||||
|             { | ||||
|                BOOST_LOG_TRIVIAL(warning) | ||||
|                   << logPrefix_ << "Reached end of file (3)"; | ||||
|                messageValid = false; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                if (zone.opCode > 2) | ||||
|                { | ||||
|                   BOOST_LOG_TRIVIAL(warning) | ||||
|                      << logPrefix_ << "Invalid op code: " << zone.opCode; | ||||
|                   messageValid = false; | ||||
|                } | ||||
|                if (zone.endRange > 511) | ||||
|                { | ||||
|                   BOOST_LOG_TRIVIAL(warning) | ||||
|                      << logPrefix_ << "Invalid end range: " << zone.endRange; | ||||
|                   messageValid = false; | ||||
|                } | ||||
|             } | ||||
|          } | ||||
|       } | ||||
|    } | ||||
| 
 | ||||
|    if (!ValidateSize(is, bytesRead)) | ||||
|    { | ||||
|       messageValid = false; | ||||
|    } | ||||
| 
 | ||||
|    if (!messageValid) | ||||
|    { | ||||
|       p->rangeZones_.resize(0); | ||||
|       p->rangeZones_.shrink_to_fit(); | ||||
|    } | ||||
| 
 | ||||
|    return messageValid; | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<ClutterFilterMap> | ||||
| ClutterFilterMap::Create(MessageHeader&& header, std::istream& is) | ||||
| { | ||||
|    std::unique_ptr<ClutterFilterMap> message = | ||||
|       std::make_unique<ClutterFilterMap>(); | ||||
|    message->set_header(std::move(header)); | ||||
|    message->Parse(is); | ||||
|    return message; | ||||
| } | ||||
| 
 | ||||
| } // namespace rda
 | ||||
| } // namespace wsr88d
 | ||||
| } // namespace scwx
 | ||||
							
								
								
									
										72
									
								
								wxdata/source/scwx/wsr88d/rda/message.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								wxdata/source/scwx/wsr88d/rda/message.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,72 @@ | |||
| #include <scwx/wsr88d/rda/message.hpp> | ||||
| 
 | ||||
| #include <istream> | ||||
| 
 | ||||
| #include <boost/log/trivial.hpp> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace wsr88d | ||||
| { | ||||
| namespace rda | ||||
| { | ||||
| 
 | ||||
| static const std::string logPrefix_ = "[scwx::wsr88d::rda::message] "; | ||||
| 
 | ||||
| class MessageImpl | ||||
| { | ||||
| public: | ||||
|    explicit MessageImpl() : header_() {}; | ||||
|    ~MessageImpl() = default; | ||||
| 
 | ||||
|    MessageHeader header_; | ||||
| }; | ||||
| 
 | ||||
| Message::Message() : p(std::make_unique<MessageImpl>()) {} | ||||
| Message::~Message() = default; | ||||
| 
 | ||||
| Message::Message(Message&&) noexcept = default; | ||||
| Message& Message::operator=(Message&&) noexcept = default; | ||||
| 
 | ||||
| bool Message::ValidateSize(std::istream& is, size_t bytesRead) const | ||||
| { | ||||
|    bool   messageValid = true; | ||||
|    size_t dataSize     = header().message_size() * 2 - header().SIZE; | ||||
| 
 | ||||
|    if (bytesRead != dataSize) | ||||
|    { | ||||
|       is.seekg(static_cast<std::streamoff>(dataSize) - | ||||
|                   static_cast<std::streamoff>(bytesRead), | ||||
|                std::ios_base::cur); | ||||
| 
 | ||||
|       if (bytesRead < dataSize) | ||||
|       { | ||||
|          BOOST_LOG_TRIVIAL(trace) | ||||
|             << logPrefix_ << "Message contents smaller than size: " << bytesRead | ||||
|             << " < " << dataSize << " bytes"; | ||||
|       } | ||||
|       if (bytesRead > dataSize) | ||||
|       { | ||||
|          BOOST_LOG_TRIVIAL(warning) | ||||
|             << logPrefix_ << "Message contents larger than size: " << bytesRead | ||||
|             << " > " << dataSize << " bytes"; | ||||
|          messageValid = false; | ||||
|       } | ||||
|    } | ||||
| 
 | ||||
|    return messageValid; | ||||
| } | ||||
| 
 | ||||
| const MessageHeader& Message::header() const | ||||
| { | ||||
|    return p->header_; | ||||
| } | ||||
| 
 | ||||
| void Message::set_header(MessageHeader&& header) | ||||
| { | ||||
|    p->header_ = std::move(header); | ||||
| } | ||||
| 
 | ||||
| } // namespace rda
 | ||||
| } // namespace wsr88d
 | ||||
| } // namespace scwx
 | ||||
							
								
								
									
										130
									
								
								wxdata/source/scwx/wsr88d/rda/message_factory.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								wxdata/source/scwx/wsr88d/rda/message_factory.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,130 @@ | |||
| #include <scwx/wsr88d/rda/message_factory.hpp> | ||||
| 
 | ||||
| #include <scwx/util/vectorbuf.hpp> | ||||
| #include <scwx/wsr88d/rda/clutter_filter_map.hpp> | ||||
| 
 | ||||
| #include <istream> | ||||
| #include <unordered_map> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include <boost/log/trivial.hpp> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace wsr88d | ||||
| { | ||||
| namespace rda | ||||
| { | ||||
| 
 | ||||
| static const std::string logPrefix_ = "[scwx::wsr88d::rda::message_factory] "; | ||||
| 
 | ||||
| typedef std::function<std::unique_ptr<Message>(MessageHeader&&, std::istream&)> | ||||
|    CreateMessageFunction; | ||||
| 
 | ||||
| static const std::unordered_map<uint8_t, CreateMessageFunction> create_ { | ||||
|    {15, ClutterFilterMap::Create}}; | ||||
| 
 | ||||
| static std::vector<char> messageData_; | ||||
| static size_t            bufferedSize_; | ||||
| static util::vectorbuf   messageBuffer_(messageData_); | ||||
| static std::istream      messageBufferStream_(&messageBuffer_); | ||||
| 
 | ||||
| MessageInfo MessageFactory::Create(std::istream& is) | ||||
| { | ||||
|    MessageInfo   info; | ||||
|    MessageHeader header; | ||||
|    info.headerValid  = header.Parse(is); | ||||
|    info.messageValid = info.headerValid; | ||||
| 
 | ||||
|    if (info.headerValid && create_.find(header.message_type()) == create_.end()) | ||||
|    { | ||||
|       BOOST_LOG_TRIVIAL(warning) | ||||
|          << logPrefix_ << "Unknown message type: " | ||||
|          << static_cast<unsigned>(header.message_type()); | ||||
|       info.messageValid = false; | ||||
|    } | ||||
| 
 | ||||
|    if (info.messageValid) | ||||
|    { | ||||
|       uint16_t segment       = header.message_segment_number(); | ||||
|       uint16_t totalSegments = header.number_of_message_segments(); | ||||
|       uint8_t  messageType   = header.message_type(); | ||||
|       size_t   dataSize      = header.message_size() * 2 - MessageHeader::SIZE; | ||||
| 
 | ||||
|       std::istream* messageStream = nullptr; | ||||
| 
 | ||||
|       if (totalSegments == 1) | ||||
|       { | ||||
|          BOOST_LOG_TRIVIAL(trace) << logPrefix_ << "Found Message " | ||||
|                                   << static_cast<unsigned>(messageType); | ||||
|          messageStream = &is; | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|          BOOST_LOG_TRIVIAL(trace) | ||||
|             << logPrefix_ << "Found Message " | ||||
|             << static_cast<unsigned>(messageType) << " Segment " << segment | ||||
|             << "/" << totalSegments; | ||||
| 
 | ||||
|          if (segment == 1) | ||||
|          { | ||||
|             // Estimate total message size
 | ||||
|             messageData_.reserve(dataSize * totalSegments); | ||||
|             bufferedSize_ = 0; | ||||
|          } | ||||
| 
 | ||||
|          if (messageData_.capacity() < bufferedSize_ + dataSize) | ||||
|          { | ||||
|             BOOST_LOG_TRIVIAL(debug) | ||||
|                << logPrefix_ << "Bad size estimate, increasing size"; | ||||
| 
 | ||||
|             // Estimate remaining size
 | ||||
|             uint16_t remainingSegments = | ||||
|                std::max<uint16_t>(totalSegments - segment + 1, 100u); | ||||
|             size_t remainingSize = remainingSegments * dataSize; | ||||
| 
 | ||||
|             messageData_.reserve(bufferedSize_ + remainingSize); | ||||
|          } | ||||
| 
 | ||||
|          is.read(messageData_.data() + bufferedSize_, dataSize); | ||||
|          bufferedSize_ += dataSize; | ||||
| 
 | ||||
|          if (is.eof()) | ||||
|          { | ||||
|             BOOST_LOG_TRIVIAL(warning) | ||||
|                << logPrefix_ << "End of file reached trying to buffer message"; | ||||
|             info.messageValid = false; | ||||
|             messageData_.shrink_to_fit(); | ||||
|             bufferedSize_ = 0; | ||||
|          } | ||||
|          else if (segment == totalSegments) | ||||
|          { | ||||
|             messageBuffer_.update_read_pointers(bufferedSize_); | ||||
|             header.set_message_size( | ||||
|                static_cast<uint16_t>(bufferedSize_ / 2 + MessageHeader::SIZE)); | ||||
| 
 | ||||
|             messageStream = &messageBufferStream_; | ||||
|          } | ||||
|       } | ||||
| 
 | ||||
|       if (messageStream != nullptr) | ||||
|       { | ||||
|          info.message = | ||||
|             create_.at(messageType)(std::move(header), *messageStream); | ||||
|          messageData_.shrink_to_fit(); | ||||
|          bufferedSize_ = 0; | ||||
|       } | ||||
|    } | ||||
|    else if (info.headerValid) | ||||
|    { | ||||
|       // Seek to the end of the current message
 | ||||
|       is.seekg(header.message_size() * 2 - rda::MessageHeader::SIZE, | ||||
|                std::ios_base::cur); | ||||
|    } | ||||
| 
 | ||||
|    return info; | ||||
| } | ||||
| 
 | ||||
| } // namespace rda
 | ||||
| } // namespace wsr88d
 | ||||
| } // namespace scwx
 | ||||
|  | @ -44,14 +44,11 @@ public: | |||
|    uint16_t messageSegmentNumber_; | ||||
| }; | ||||
| 
 | ||||
| MessageHeader::MessageHeader() : | ||||
|     p(std::make_unique<MessageHeaderImpl>()) | ||||
| { | ||||
| } | ||||
| MessageHeader::MessageHeader() : p(std::make_unique<MessageHeaderImpl>()) {} | ||||
| MessageHeader::~MessageHeader() = default; | ||||
| 
 | ||||
| MessageHeader::MessageHeader(MessageHeader&&) noexcept = default; | ||||
| MessageHeader& MessageHeader::operator=(MessageHeader&&) = default; | ||||
| MessageHeader& MessageHeader::operator=(MessageHeader&&) noexcept = default; | ||||
| 
 | ||||
| uint16_t MessageHeader::message_size() const | ||||
| { | ||||
|  | @ -93,6 +90,11 @@ uint16_t MessageHeader::message_segment_number() const | |||
|    return p->messageSegmentNumber_; | ||||
| } | ||||
| 
 | ||||
| void MessageHeader::set_message_size(uint16_t messageSize) | ||||
| { | ||||
|    p->messageSize_ = messageSize; | ||||
| } | ||||
| 
 | ||||
| bool MessageHeader::Parse(std::istream& is) | ||||
| { | ||||
|    bool headerValid = true; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat