diff --git a/wxdata/include/scwx/wsr88d/rpg/tabular_alphanumeric_block.hpp b/wxdata/include/scwx/wsr88d/rpg/tabular_alphanumeric_block.hpp index 8c39a8db..ee2cf369 100644 --- a/wxdata/include/scwx/wsr88d/rpg/tabular_alphanumeric_block.hpp +++ b/wxdata/include/scwx/wsr88d/rpg/tabular_alphanumeric_block.hpp @@ -32,6 +32,7 @@ public: size_t data_size() const override; bool Parse(std::istream& is); + bool Parse(std::istream& is, bool skipHeader); static constexpr size_t SIZE = 102u; diff --git a/wxdata/source/scwx/wsr88d/level3_file.cpp b/wxdata/source/scwx/wsr88d/level3_file.cpp index 3850d00f..4f53ea49 100644 --- a/wxdata/source/scwx/wsr88d/level3_file.cpp +++ b/wxdata/source/scwx/wsr88d/level3_file.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -24,6 +25,8 @@ namespace wsr88d static const std::string logPrefix_ = "[scwx::wsr88d::level3_file] "; +static const std::set standaloneTabularProducts_ = {62, 75, 77, 82}; + class Level3FileImpl { public: @@ -259,15 +262,27 @@ bool Level3FileImpl::LoadBlocks(std::istream& is) BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Loading Blocks"; + bool skipTabularHeader = false; + std::streampos offsetBasePos = is.tellg(); constexpr size_t offsetBase = rpg::Level3MessageHeader::SIZE + rpg::ProductDescriptionBlock::SIZE; - const size_t offsetToSymbology = - descriptionBlock_->offset_to_symbology() * 2u; - const size_t offsetToGraphic = descriptionBlock_->offset_to_graphic() * 2u; - const size_t offsetToTabular = descriptionBlock_->offset_to_tabular() * 2u; + size_t offsetToSymbology = descriptionBlock_->offset_to_symbology() * 2u; + size_t offsetToGraphic = descriptionBlock_->offset_to_graphic() * 2u; + 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) { @@ -308,7 +323,7 @@ bool Level3FileImpl::LoadBlocks(std::istream& is) tabularBlock_ = std::make_shared(); is.seekg(offsetToTabular - offsetBase, std::ios_base::cur); - tabularValid = tabularBlock_->Parse(is); + tabularValid = tabularBlock_->Parse(is, skipTabularHeader); is.seekg(offsetBasePos, std::ios_base::beg); BOOST_LOG_TRIVIAL(debug) diff --git a/wxdata/source/scwx/wsr88d/rpg/tabular_alphanumeric_block.cpp b/wxdata/source/scwx/wsr88d/rpg/tabular_alphanumeric_block.cpp index 73c0552e..39db8119 100644 --- a/wxdata/source/scwx/wsr88d/rpg/tabular_alphanumeric_block.cpp +++ b/wxdata/source/scwx/wsr88d/rpg/tabular_alphanumeric_block.cpp @@ -69,66 +69,75 @@ size_t TabularAlphanumericBlock::data_size() const } bool TabularAlphanumericBlock::Parse(std::istream& is) +{ + return Parse(is, false); +} + +bool TabularAlphanumericBlock::Parse(std::istream& is, bool skipHeader) { bool blockValid = true; const std::streampos blockStart = is.tellg(); - is.read(reinterpret_cast(&p->blockDivider1_), 2); - is.read(reinterpret_cast(&p->blockId_), 2); - is.read(reinterpret_cast(&p->lengthOfBlock_), 4); - - p->blockDivider1_ = ntohs(p->blockDivider1_); - p->blockId_ = ntohs(p->blockId_); - p->lengthOfBlock_ = ntohl(p->lengthOfBlock_); - - if (is.eof()) + if (!skipHeader) { - BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Reached end of file"; - blockValid = false; - } - else - { - if (p->blockDivider1_ != -1) + + is.read(reinterpret_cast(&p->blockDivider1_), 2); + is.read(reinterpret_cast(&p->blockId_), 2); + is.read(reinterpret_cast(&p->lengthOfBlock_), 4); + + p->blockDivider1_ = ntohs(p->blockDivider1_); + p->blockId_ = ntohs(p->blockId_); + p->lengthOfBlock_ = ntohl(p->lengthOfBlock_); + + if (is.eof()) { - BOOST_LOG_TRIVIAL(warning) - << logPrefix_ - << "Invalid first block divider: " << p->blockDivider1_; + BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Reached end of file"; blockValid = false; } - if (p->blockId_ != 3) + else { - BOOST_LOG_TRIVIAL(warning) - << logPrefix_ << "Invalid block ID: " << p->blockId_; - blockValid = false; + if (p->blockDivider1_ != -1) + { + 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) - << logPrefix_ << "Invalid block length: " << p->lengthOfBlock_; - blockValid = false; + p->messageHeader_ = std::make_shared(); + blockValid = p->messageHeader_->Parse(is); + + if (!blockValid) + { + p->messageHeader_ = nullptr; + } } - } - if (blockValid) - { - p->messageHeader_ = std::make_shared(); - blockValid = p->messageHeader_->Parse(is); - - if (!blockValid) + if (blockValid) { - p->messageHeader_ = nullptr; - } - } + p->descriptionBlock_ = std::make_shared(); + blockValid = p->descriptionBlock_->Parse(is); - if (blockValid) - { - p->descriptionBlock_ = std::make_shared(); - blockValid = p->descriptionBlock_->Parse(is); - - if (!blockValid) - { - p->descriptionBlock_ = nullptr; + if (!blockValid) + { + p->descriptionBlock_ = nullptr; + } } } @@ -196,10 +205,15 @@ bool TabularAlphanumericBlock::Parse(std::istream& is) const std::streampos blockEnd = is.tellg(); - if (!ValidateMessage(is, blockEnd - blockStart)) + if (!skipHeader && !ValidateMessage(is, blockEnd - blockStart)) { blockValid = false; } + else if (skipHeader && is.eof()) + { + BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Reached end of file"; + blockValid = false; + } return blockValid; }