Standalone tabular alphanumeric product message

This commit is contained in:
Dan Paulat 2022-01-12 19:45:21 -06:00
parent 0b063f6e8c
commit 235c060b17
3 changed files with 80 additions and 50 deletions

View file

@ -32,6 +32,7 @@ public:
size_t data_size() const override; size_t data_size() const override;
bool Parse(std::istream& is); bool Parse(std::istream& is);
bool Parse(std::istream& is, bool skipHeader);
static constexpr size_t SIZE = 102u; static constexpr size_t SIZE = 102u;

View file

@ -10,6 +10,7 @@
#include <scwx/util/time.hpp> #include <scwx/util/time.hpp>
#include <fstream> #include <fstream>
#include <set>
#include <boost/iostreams/copy.hpp> #include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filtering_streambuf.hpp> #include <boost/iostreams/filtering_streambuf.hpp>
@ -24,6 +25,8 @@ namespace wsr88d
static const std::string logPrefix_ = "[scwx::wsr88d::level3_file] "; static const std::string logPrefix_ = "[scwx::wsr88d::level3_file] ";
static const std::set<int16_t> standaloneTabularProducts_ = {62, 75, 77, 82};
class Level3FileImpl class Level3FileImpl
{ {
public: public:
@ -259,15 +262,27 @@ bool Level3FileImpl::LoadBlocks(std::istream& is)
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Loading Blocks"; BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Loading Blocks";
bool skipTabularHeader = false;
std::streampos offsetBasePos = is.tellg(); std::streampos offsetBasePos = is.tellg();
constexpr size_t offsetBase = constexpr size_t offsetBase =
rpg::Level3MessageHeader::SIZE + rpg::ProductDescriptionBlock::SIZE; rpg::Level3MessageHeader::SIZE + rpg::ProductDescriptionBlock::SIZE;
const size_t offsetToSymbology = size_t offsetToSymbology = descriptionBlock_->offset_to_symbology() * 2u;
descriptionBlock_->offset_to_symbology() * 2u; size_t offsetToGraphic = descriptionBlock_->offset_to_graphic() * 2u;
const size_t offsetToGraphic = descriptionBlock_->offset_to_graphic() * 2u; size_t offsetToTabular = descriptionBlock_->offset_to_tabular() * 2u;
const size_t offsetToTabular = descriptionBlock_->offset_to_tabular() * 2u;
if (standaloneTabularProducts_.contains(messageHeader_->message_code()))
{
// These products are completely alphanumeric, and do not contain a
// symbology block.
offsetToTabular = offsetToSymbology;
offsetToSymbology = 0;
offsetToGraphic = 0;
skipTabularHeader = true;
}
if (offsetToSymbology >= offsetBase) if (offsetToSymbology >= offsetBase)
{ {
@ -308,7 +323,7 @@ bool Level3FileImpl::LoadBlocks(std::istream& is)
tabularBlock_ = std::make_shared<rpg::TabularAlphanumericBlock>(); tabularBlock_ = std::make_shared<rpg::TabularAlphanumericBlock>();
is.seekg(offsetToTabular - offsetBase, std::ios_base::cur); is.seekg(offsetToTabular - offsetBase, std::ios_base::cur);
tabularValid = tabularBlock_->Parse(is); tabularValid = tabularBlock_->Parse(is, skipTabularHeader);
is.seekg(offsetBasePos, std::ios_base::beg); is.seekg(offsetBasePos, std::ios_base::beg);
BOOST_LOG_TRIVIAL(debug) BOOST_LOG_TRIVIAL(debug)

View file

@ -69,66 +69,75 @@ size_t TabularAlphanumericBlock::data_size() const
} }
bool TabularAlphanumericBlock::Parse(std::istream& is) bool TabularAlphanumericBlock::Parse(std::istream& is)
{
return Parse(is, false);
}
bool TabularAlphanumericBlock::Parse(std::istream& is, bool skipHeader)
{ {
bool blockValid = true; bool blockValid = true;
const std::streampos blockStart = is.tellg(); const std::streampos blockStart = is.tellg();
is.read(reinterpret_cast<char*>(&p->blockDivider1_), 2); if (!skipHeader)
is.read(reinterpret_cast<char*>(&p->blockId_), 2);
is.read(reinterpret_cast<char*>(&p->lengthOfBlock_), 4);
p->blockDivider1_ = ntohs(p->blockDivider1_);
p->blockId_ = ntohs(p->blockId_);
p->lengthOfBlock_ = ntohl(p->lengthOfBlock_);
if (is.eof())
{ {
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Reached end of file";
blockValid = false; is.read(reinterpret_cast<char*>(&p->blockDivider1_), 2);
} is.read(reinterpret_cast<char*>(&p->blockId_), 2);
else is.read(reinterpret_cast<char*>(&p->lengthOfBlock_), 4);
{
if (p->blockDivider1_ != -1) p->blockDivider1_ = ntohs(p->blockDivider1_);
p->blockId_ = ntohs(p->blockId_);
p->lengthOfBlock_ = ntohl(p->lengthOfBlock_);
if (is.eof())
{ {
BOOST_LOG_TRIVIAL(warning) BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Reached end of file";
<< logPrefix_
<< "Invalid first block divider: " << p->blockDivider1_;
blockValid = false; blockValid = false;
} }
if (p->blockId_ != 3) else
{ {
BOOST_LOG_TRIVIAL(warning) if (p->blockDivider1_ != -1)
<< logPrefix_ << "Invalid block ID: " << p->blockId_; {
blockValid = false; BOOST_LOG_TRIVIAL(warning)
<< logPrefix_
<< "Invalid first block divider: " << p->blockDivider1_;
blockValid = false;
}
if (p->blockId_ != 3)
{
BOOST_LOG_TRIVIAL(warning)
<< logPrefix_ << "Invalid block ID: " << p->blockId_;
blockValid = false;
}
if (p->lengthOfBlock_ < 10)
{
BOOST_LOG_TRIVIAL(warning)
<< logPrefix_ << "Invalid block length: " << p->lengthOfBlock_;
blockValid = false;
}
} }
if (p->lengthOfBlock_ < 10)
if (blockValid)
{ {
BOOST_LOG_TRIVIAL(warning) p->messageHeader_ = std::make_shared<Level3MessageHeader>();
<< logPrefix_ << "Invalid block length: " << p->lengthOfBlock_; blockValid = p->messageHeader_->Parse(is);
blockValid = false;
if (!blockValid)
{
p->messageHeader_ = nullptr;
}
} }
}
if (blockValid) if (blockValid)
{
p->messageHeader_ = std::make_shared<Level3MessageHeader>();
blockValid = p->messageHeader_->Parse(is);
if (!blockValid)
{ {
p->messageHeader_ = nullptr; p->descriptionBlock_ = std::make_shared<ProductDescriptionBlock>();
} blockValid = p->descriptionBlock_->Parse(is);
}
if (blockValid) if (!blockValid)
{ {
p->descriptionBlock_ = std::make_shared<ProductDescriptionBlock>(); p->descriptionBlock_ = nullptr;
blockValid = p->descriptionBlock_->Parse(is); }
if (!blockValid)
{
p->descriptionBlock_ = nullptr;
} }
} }
@ -196,10 +205,15 @@ bool TabularAlphanumericBlock::Parse(std::istream& is)
const std::streampos blockEnd = is.tellg(); const std::streampos blockEnd = is.tellg();
if (!ValidateMessage(is, blockEnd - blockStart)) if (!skipHeader && !ValidateMessage(is, blockEnd - blockStart))
{ {
blockValid = false; blockValid = false;
} }
else if (skipHeader && is.eof())
{
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Reached end of file";
blockValid = false;
}
return blockValid; return blockValid;
} }