mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 19:10:06 +00:00
Refactoring to unique product message types, in order to support more products
This commit is contained in:
parent
235c060b17
commit
dc545f19e9
11 changed files with 742 additions and 177 deletions
|
|
@ -1,20 +1,12 @@
|
|||
#include <scwx/wsr88d/level3_file.hpp>
|
||||
#include <scwx/wsr88d/rpg/ccb_header.hpp>
|
||||
#include <scwx/wsr88d/rpg/graphic_alphanumeric_block.hpp>
|
||||
#include <scwx/wsr88d/rpg/level3_message_header.hpp>
|
||||
#include <scwx/wsr88d/rpg/product_description_block.hpp>
|
||||
#include <scwx/wsr88d/rpg/product_symbology_block.hpp>
|
||||
#include <scwx/wsr88d/rpg/tabular_alphanumeric_block.hpp>
|
||||
#include <scwx/wsr88d/rpg/level3_message_factory.hpp>
|
||||
#include <scwx/wsr88d/rpg/wmo_header.hpp>
|
||||
#include <scwx/util/rangebuf.hpp>
|
||||
#include <scwx/util/time.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
|
||||
#include <boost/iostreams/copy.hpp>
|
||||
#include <boost/iostreams/filtering_streambuf.hpp>
|
||||
#include <boost/iostreams/filter/bzip2.hpp>
|
||||
#include <boost/iostreams/filter/zlib.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
|
|
@ -25,33 +17,20 @@ namespace wsr88d
|
|||
|
||||
static const std::string logPrefix_ = "[scwx::wsr88d::level3_file] ";
|
||||
|
||||
static const std::set<int16_t> standaloneTabularProducts_ = {62, 75, 77, 82};
|
||||
|
||||
class Level3FileImpl
|
||||
{
|
||||
public:
|
||||
explicit Level3FileImpl() :
|
||||
wmoHeader_ {},
|
||||
ccbHeader_ {},
|
||||
messageHeader_ {},
|
||||
descriptionBlock_ {},
|
||||
symbologyBlock_ {},
|
||||
graphicBlock_ {},
|
||||
tabularBlock_ {} {};
|
||||
wmoHeader_ {}, ccbHeader_ {}, innerHeader_ {}, message_ {} {};
|
||||
~Level3FileImpl() = default;
|
||||
|
||||
bool DecompressFile(std::istream& is, std::stringstream& ss);
|
||||
bool LoadFileData(std::istream& is);
|
||||
bool LoadBlocks(std::istream& is);
|
||||
|
||||
std::shared_ptr<rpg::WmoHeader> wmoHeader_;
|
||||
std::shared_ptr<rpg::CcbHeader> ccbHeader_;
|
||||
std::shared_ptr<rpg::WmoHeader> innerHeader_;
|
||||
std::shared_ptr<rpg::Level3MessageHeader> messageHeader_;
|
||||
std::shared_ptr<rpg::ProductDescriptionBlock> descriptionBlock_;
|
||||
std::shared_ptr<rpg::ProductSymbologyBlock> symbologyBlock_;
|
||||
std::shared_ptr<rpg::GraphicAlphanumericBlock> graphicBlock_;
|
||||
std::shared_ptr<rpg::TabularAlphanumericBlock> tabularBlock_;
|
||||
std::shared_ptr<rpg::WmoHeader> wmoHeader_;
|
||||
std::shared_ptr<rpg::CcbHeader> ccbHeader_;
|
||||
std::shared_ptr<rpg::WmoHeader> innerHeader_;
|
||||
std::shared_ptr<rpg::Level3Message> message_;
|
||||
};
|
||||
|
||||
Level3File::Level3File() : p(std::make_unique<Level3FileImpl>()) {}
|
||||
|
|
@ -60,15 +39,9 @@ Level3File::~Level3File() = default;
|
|||
Level3File::Level3File(Level3File&&) noexcept = default;
|
||||
Level3File& Level3File::operator=(Level3File&&) noexcept = default;
|
||||
|
||||
std::shared_ptr<rpg::Level3MessageHeader> Level3File::message_header() const
|
||||
std::shared_ptr<rpg::Level3Message> Level3File::message() const
|
||||
{
|
||||
return p->messageHeader_;
|
||||
}
|
||||
|
||||
std::shared_ptr<rpg::ProductSymbologyBlock>
|
||||
Level3File::product_symbology_block() const
|
||||
{
|
||||
return p->symbologyBlock_;
|
||||
return p->message_;
|
||||
}
|
||||
|
||||
bool Level3File::LoadFile(const std::string& filename)
|
||||
|
|
@ -197,145 +170,9 @@ bool Level3FileImpl::DecompressFile(std::istream& is, std::stringstream& ss)
|
|||
|
||||
bool Level3FileImpl::LoadFileData(std::istream& is)
|
||||
{
|
||||
messageHeader_ = std::make_shared<rpg::Level3MessageHeader>();
|
||||
message_ = rpg::Level3MessageFactory::Create(is);
|
||||
|
||||
bool dataValid = messageHeader_->Parse(is);
|
||||
|
||||
if (dataValid)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< logPrefix_ << "Code: " << messageHeader_->message_code();
|
||||
|
||||
descriptionBlock_ = std::make_shared<rpg::ProductDescriptionBlock>();
|
||||
|
||||
dataValid = descriptionBlock_->Parse(is);
|
||||
}
|
||||
|
||||
if (dataValid)
|
||||
{
|
||||
if (descriptionBlock_->IsCompressionEnabled())
|
||||
{
|
||||
size_t messageLength = messageHeader_->length_of_message();
|
||||
size_t prefixLength =
|
||||
rpg::Level3MessageHeader::SIZE + rpg::ProductDescriptionBlock::SIZE;
|
||||
size_t recordSize =
|
||||
(messageLength > prefixLength) ? messageLength - prefixLength : 0;
|
||||
|
||||
boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
|
||||
util::rangebuf r(is.rdbuf(), recordSize);
|
||||
in.push(boost::iostreams::bzip2_decompressor());
|
||||
in.push(r);
|
||||
|
||||
try
|
||||
{
|
||||
std::stringstream ss;
|
||||
std::streamsize bytesCopied = boost::iostreams::copy(in, ss);
|
||||
BOOST_LOG_TRIVIAL(trace)
|
||||
<< logPrefix_ << "Decompressed data size = " << bytesCopied
|
||||
<< " bytes";
|
||||
|
||||
dataValid = LoadBlocks(ss);
|
||||
}
|
||||
catch (const boost::iostreams::bzip2_error& ex)
|
||||
{
|
||||
int error = ex.error();
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Error decompressing data: " << ex.what();
|
||||
|
||||
dataValid = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dataValid = LoadBlocks(is);
|
||||
}
|
||||
}
|
||||
|
||||
return dataValid;
|
||||
}
|
||||
|
||||
bool Level3FileImpl::LoadBlocks(std::istream& is)
|
||||
{
|
||||
bool symbologyValid = true;
|
||||
bool graphicValid = true;
|
||||
bool tabularValid = true;
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
symbologyBlock_ = std::make_shared<rpg::ProductSymbologyBlock>();
|
||||
|
||||
is.seekg(offsetToSymbology - offsetBase, std::ios_base::cur);
|
||||
symbologyValid = symbologyBlock_->Parse(is);
|
||||
is.seekg(offsetBasePos, std::ios_base::beg);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< logPrefix_ << "Product symbology block valid: " << symbologyValid;
|
||||
|
||||
if (!symbologyValid)
|
||||
{
|
||||
symbologyBlock_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (offsetToGraphic >= offsetBase)
|
||||
{
|
||||
graphicBlock_ = std::make_shared<rpg::GraphicAlphanumericBlock>();
|
||||
|
||||
is.seekg(offsetToGraphic - offsetBase, std::ios_base::cur);
|
||||
graphicValid = graphicBlock_->Parse(is);
|
||||
is.seekg(offsetBasePos, std::ios_base::beg);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< logPrefix_ << "Graphic alphanumeric block valid: " << graphicValid;
|
||||
|
||||
if (!graphicValid)
|
||||
{
|
||||
graphicBlock_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (offsetToTabular >= offsetBase)
|
||||
{
|
||||
tabularBlock_ = std::make_shared<rpg::TabularAlphanumericBlock>();
|
||||
|
||||
is.seekg(offsetToTabular - offsetBase, std::ios_base::cur);
|
||||
tabularValid = tabularBlock_->Parse(is, skipTabularHeader);
|
||||
is.seekg(offsetBasePos, std::ios_base::beg);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< logPrefix_ << "Tabular alphanumeric block valid: " << tabularValid;
|
||||
|
||||
if (!tabularValid)
|
||||
{
|
||||
tabularBlock_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return (symbologyValid && graphicValid && tabularValid);
|
||||
return (message_ != nullptr);
|
||||
}
|
||||
|
||||
} // namespace wsr88d
|
||||
|
|
|
|||
223
wxdata/source/scwx/wsr88d/rpg/graphic_product_message.cpp
Normal file
223
wxdata/source/scwx/wsr88d/rpg/graphic_product_message.cpp
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
#include <scwx/wsr88d/rpg/graphic_product_message.hpp>
|
||||
#include <scwx/util/rangebuf.hpp>
|
||||
|
||||
#include <istream>
|
||||
#include <string>
|
||||
|
||||
#include <boost/iostreams/copy.hpp>
|
||||
#include <boost/iostreams/filtering_streambuf.hpp>
|
||||
#include <boost/iostreams/filter/bzip2.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace wsr88d
|
||||
{
|
||||
namespace rpg
|
||||
{
|
||||
|
||||
static const std::string logPrefix_ =
|
||||
"[scwx::wsr88d::rpg::graphic_product_message] ";
|
||||
|
||||
class GraphicProductMessageImpl
|
||||
{
|
||||
public:
|
||||
explicit GraphicProductMessageImpl() :
|
||||
descriptionBlock_ {0},
|
||||
symbologyBlock_ {0},
|
||||
graphicBlock_ {0},
|
||||
tabularBlock_ {0}
|
||||
{
|
||||
}
|
||||
~GraphicProductMessageImpl() = default;
|
||||
|
||||
bool LoadBlocks(std::istream& is);
|
||||
|
||||
std::shared_ptr<ProductDescriptionBlock> descriptionBlock_;
|
||||
std::shared_ptr<ProductSymbologyBlock> symbologyBlock_;
|
||||
std::shared_ptr<GraphicAlphanumericBlock> graphicBlock_;
|
||||
std::shared_ptr<TabularAlphanumericBlock> tabularBlock_;
|
||||
};
|
||||
|
||||
GraphicProductMessage::GraphicProductMessage() :
|
||||
p(std::make_unique<GraphicProductMessageImpl>())
|
||||
{
|
||||
}
|
||||
GraphicProductMessage::~GraphicProductMessage() = default;
|
||||
|
||||
GraphicProductMessage::GraphicProductMessage(GraphicProductMessage&&) noexcept =
|
||||
default;
|
||||
GraphicProductMessage&
|
||||
GraphicProductMessage::operator=(GraphicProductMessage&&) noexcept = default;
|
||||
|
||||
std::shared_ptr<ProductDescriptionBlock>
|
||||
GraphicProductMessage::description_block() const
|
||||
{
|
||||
return p->descriptionBlock_;
|
||||
}
|
||||
|
||||
std::shared_ptr<ProductSymbologyBlock>
|
||||
GraphicProductMessage::symbology_block() const
|
||||
{
|
||||
return p->symbologyBlock_;
|
||||
}
|
||||
|
||||
std::shared_ptr<GraphicAlphanumericBlock>
|
||||
GraphicProductMessage::graphic_block() const
|
||||
{
|
||||
return p->graphicBlock_;
|
||||
}
|
||||
|
||||
std::shared_ptr<TabularAlphanumericBlock>
|
||||
GraphicProductMessage::tabular_block() const
|
||||
{
|
||||
return p->tabularBlock_;
|
||||
}
|
||||
|
||||
bool GraphicProductMessage::Parse(std::istream& is)
|
||||
{
|
||||
bool dataValid = true;
|
||||
|
||||
const std::streampos dataStart = is.tellg();
|
||||
|
||||
p->descriptionBlock_ = std::make_shared<ProductDescriptionBlock>();
|
||||
dataValid = p->descriptionBlock_->Parse(is);
|
||||
|
||||
if (dataValid)
|
||||
{
|
||||
if (p->descriptionBlock_->IsCompressionEnabled())
|
||||
{
|
||||
size_t messageLength = header().length_of_message();
|
||||
size_t prefixLength =
|
||||
Level3MessageHeader::SIZE + ProductDescriptionBlock::SIZE;
|
||||
size_t recordSize =
|
||||
(messageLength > prefixLength) ? messageLength - prefixLength : 0;
|
||||
|
||||
boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
|
||||
util::rangebuf r(is.rdbuf(), recordSize);
|
||||
in.push(boost::iostreams::bzip2_decompressor());
|
||||
in.push(r);
|
||||
|
||||
try
|
||||
{
|
||||
std::stringstream ss;
|
||||
std::streamsize bytesCopied = boost::iostreams::copy(in, ss);
|
||||
BOOST_LOG_TRIVIAL(trace)
|
||||
<< logPrefix_ << "Decompressed data size = " << bytesCopied
|
||||
<< " bytes";
|
||||
|
||||
dataValid = p->LoadBlocks(ss);
|
||||
}
|
||||
catch (const boost::iostreams::bzip2_error& ex)
|
||||
{
|
||||
int error = ex.error();
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Error decompressing data: " << ex.what();
|
||||
|
||||
dataValid = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dataValid = p->LoadBlocks(is);
|
||||
}
|
||||
}
|
||||
|
||||
const std::streampos dataEnd = is.tellg();
|
||||
if (!ValidateMessage(is, dataEnd - dataStart))
|
||||
{
|
||||
dataValid = false;
|
||||
}
|
||||
|
||||
return dataValid;
|
||||
}
|
||||
|
||||
bool GraphicProductMessageImpl::LoadBlocks(std::istream& is)
|
||||
{
|
||||
bool symbologyValid = true;
|
||||
bool graphicValid = true;
|
||||
bool tabularValid = true;
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Loading Blocks";
|
||||
|
||||
std::streampos offsetBasePos = is.tellg();
|
||||
|
||||
constexpr size_t offsetBase =
|
||||
Level3MessageHeader::SIZE + ProductDescriptionBlock::SIZE;
|
||||
|
||||
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 (offsetToSymbology >= offsetBase)
|
||||
{
|
||||
symbologyBlock_ = std::make_shared<ProductSymbologyBlock>();
|
||||
|
||||
is.seekg(offsetToSymbology - offsetBase, std::ios_base::cur);
|
||||
symbologyValid = symbologyBlock_->Parse(is);
|
||||
is.seekg(offsetBasePos, std::ios_base::beg);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< logPrefix_ << "Product symbology block valid: " << symbologyValid;
|
||||
|
||||
if (!symbologyValid)
|
||||
{
|
||||
symbologyBlock_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (offsetToGraphic >= offsetBase)
|
||||
{
|
||||
graphicBlock_ = std::make_shared<GraphicAlphanumericBlock>();
|
||||
|
||||
is.seekg(offsetToGraphic - offsetBase, std::ios_base::cur);
|
||||
graphicValid = graphicBlock_->Parse(is);
|
||||
is.seekg(offsetBasePos, std::ios_base::beg);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< logPrefix_ << "Graphic alphanumeric block valid: " << graphicValid;
|
||||
|
||||
if (!graphicValid)
|
||||
{
|
||||
graphicBlock_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (offsetToTabular >= offsetBase)
|
||||
{
|
||||
tabularBlock_ = std::make_shared<TabularAlphanumericBlock>();
|
||||
|
||||
is.seekg(offsetToTabular - offsetBase, std::ios_base::cur);
|
||||
tabularValid = tabularBlock_->Parse(is);
|
||||
is.seekg(offsetBasePos, std::ios_base::beg);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< logPrefix_ << "Tabular alphanumeric block valid: " << tabularValid;
|
||||
|
||||
if (!tabularValid)
|
||||
{
|
||||
tabularBlock_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return (symbologyValid && graphicValid && tabularValid);
|
||||
}
|
||||
|
||||
std::shared_ptr<GraphicProductMessage>
|
||||
GraphicProductMessage::Create(Level3MessageHeader&& header, std::istream& is)
|
||||
{
|
||||
std::shared_ptr<GraphicProductMessage> message =
|
||||
std::make_shared<GraphicProductMessage>();
|
||||
message->set_header(std::move(header));
|
||||
|
||||
if (!message->Parse(is))
|
||||
{
|
||||
message.reset();
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
} // namespace rpg
|
||||
} // namespace wsr88d
|
||||
} // namespace scwx
|
||||
49
wxdata/source/scwx/wsr88d/rpg/level3_message.cpp
Normal file
49
wxdata/source/scwx/wsr88d/rpg/level3_message.cpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include <scwx/wsr88d/rpg/level3_message.hpp>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace wsr88d
|
||||
{
|
||||
namespace rpg
|
||||
{
|
||||
|
||||
static const std::string logPrefix_ = "[scwx::wsr88d::rpg::level3_message] ";
|
||||
|
||||
class Level3MessageImpl
|
||||
{
|
||||
public:
|
||||
explicit Level3MessageImpl() : header_() {};
|
||||
~Level3MessageImpl() = default;
|
||||
|
||||
Level3MessageHeader header_;
|
||||
};
|
||||
|
||||
Level3Message::Level3Message() :
|
||||
Message(), p(std::make_unique<Level3MessageImpl>())
|
||||
{
|
||||
}
|
||||
Level3Message::~Level3Message() = default;
|
||||
|
||||
Level3Message::Level3Message(Level3Message&&) noexcept = default;
|
||||
Level3Message& Level3Message::operator=(Level3Message&&) noexcept = default;
|
||||
|
||||
size_t Level3Message::data_size() const
|
||||
{
|
||||
return (header().length_of_message() - header().SIZE);
|
||||
}
|
||||
|
||||
const Level3MessageHeader& Level3Message::header() const
|
||||
{
|
||||
return p->header_;
|
||||
}
|
||||
|
||||
void Level3Message::set_header(Level3MessageHeader&& header)
|
||||
{
|
||||
p->header_ = std::move(header);
|
||||
}
|
||||
|
||||
} // namespace rpg
|
||||
} // namespace wsr88d
|
||||
} // namespace scwx
|
||||
154
wxdata/source/scwx/wsr88d/rpg/level3_message_factory.cpp
Normal file
154
wxdata/source/scwx/wsr88d/rpg/level3_message_factory.cpp
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
#include <scwx/wsr88d/rpg/level3_message_factory.hpp>
|
||||
|
||||
#include <scwx/util/vectorbuf.hpp>
|
||||
#include <scwx/wsr88d/rpg/graphic_product_message.hpp>
|
||||
#include <scwx/wsr88d/rpg/tabular_product_message.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace wsr88d
|
||||
{
|
||||
namespace rpg
|
||||
{
|
||||
|
||||
static const std::string logPrefix_ =
|
||||
"[scwx::wsr88d::rpg::level3_message_factory] ";
|
||||
|
||||
typedef std::function<std::shared_ptr<Level3Message>(Level3MessageHeader&&,
|
||||
std::istream&)>
|
||||
CreateLevel3MessageFunction;
|
||||
|
||||
static const std::unordered_map<int16_t, CreateLevel3MessageFunction> //
|
||||
create_ {{19, GraphicProductMessage::Create},
|
||||
{20, GraphicProductMessage::Create},
|
||||
{27, GraphicProductMessage::Create},
|
||||
{30, GraphicProductMessage::Create},
|
||||
{31, GraphicProductMessage::Create},
|
||||
{32, GraphicProductMessage::Create},
|
||||
{37, GraphicProductMessage::Create},
|
||||
{38, GraphicProductMessage::Create},
|
||||
{41, GraphicProductMessage::Create},
|
||||
{48, GraphicProductMessage::Create},
|
||||
{49, GraphicProductMessage::Create},
|
||||
{50, GraphicProductMessage::Create},
|
||||
{51, GraphicProductMessage::Create},
|
||||
{56, GraphicProductMessage::Create},
|
||||
{57, GraphicProductMessage::Create},
|
||||
{58, GraphicProductMessage::Create},
|
||||
{59, GraphicProductMessage::Create},
|
||||
{61, GraphicProductMessage::Create},
|
||||
{62, TabularProductMessage::Create},
|
||||
{65, GraphicProductMessage::Create},
|
||||
{66, GraphicProductMessage::Create},
|
||||
{67, GraphicProductMessage::Create},
|
||||
{75, TabularProductMessage::Create},
|
||||
{77, TabularProductMessage::Create},
|
||||
{78, GraphicProductMessage::Create},
|
||||
{79, GraphicProductMessage::Create},
|
||||
{80, GraphicProductMessage::Create},
|
||||
{81, GraphicProductMessage::Create},
|
||||
{82, TabularProductMessage::Create},
|
||||
{84, GraphicProductMessage::Create},
|
||||
{86, GraphicProductMessage::Create},
|
||||
{90, GraphicProductMessage::Create},
|
||||
{93, GraphicProductMessage::Create},
|
||||
{94, GraphicProductMessage::Create},
|
||||
{97, GraphicProductMessage::Create},
|
||||
{98, GraphicProductMessage::Create},
|
||||
{99, GraphicProductMessage::Create},
|
||||
{100, GraphicProductMessage::Create},
|
||||
{101, GraphicProductMessage::Create},
|
||||
{102, GraphicProductMessage::Create},
|
||||
{104, GraphicProductMessage::Create},
|
||||
{105, GraphicProductMessage::Create},
|
||||
{107, GraphicProductMessage::Create},
|
||||
{108, GraphicProductMessage::Create},
|
||||
{109, GraphicProductMessage::Create},
|
||||
{110, GraphicProductMessage::Create},
|
||||
{111, GraphicProductMessage::Create},
|
||||
{113, GraphicProductMessage::Create},
|
||||
{132, GraphicProductMessage::Create},
|
||||
{133, GraphicProductMessage::Create},
|
||||
{134, GraphicProductMessage::Create},
|
||||
{135, GraphicProductMessage::Create},
|
||||
{137, GraphicProductMessage::Create},
|
||||
{138, GraphicProductMessage::Create},
|
||||
{140, GraphicProductMessage::Create},
|
||||
{141, GraphicProductMessage::Create},
|
||||
{143, GraphicProductMessage::Create},
|
||||
{144, GraphicProductMessage::Create},
|
||||
{145, GraphicProductMessage::Create},
|
||||
{146, GraphicProductMessage::Create},
|
||||
{147, GraphicProductMessage::Create},
|
||||
{149, GraphicProductMessage::Create},
|
||||
{150, GraphicProductMessage::Create},
|
||||
{151, GraphicProductMessage::Create},
|
||||
{152, GraphicProductMessage::Create},
|
||||
{153, GraphicProductMessage::Create},
|
||||
{154, GraphicProductMessage::Create},
|
||||
{155, GraphicProductMessage::Create},
|
||||
{159, GraphicProductMessage::Create},
|
||||
{161, GraphicProductMessage::Create},
|
||||
{163, GraphicProductMessage::Create},
|
||||
{165, GraphicProductMessage::Create},
|
||||
{166, GraphicProductMessage::Create},
|
||||
{167, GraphicProductMessage::Create},
|
||||
{168, GraphicProductMessage::Create},
|
||||
{169, GraphicProductMessage::Create},
|
||||
{170, GraphicProductMessage::Create},
|
||||
{171, GraphicProductMessage::Create},
|
||||
{172, GraphicProductMessage::Create},
|
||||
{173, GraphicProductMessage::Create},
|
||||
{174, GraphicProductMessage::Create},
|
||||
{175, GraphicProductMessage::Create},
|
||||
{176, GraphicProductMessage::Create},
|
||||
{177, GraphicProductMessage::Create},
|
||||
{178, GraphicProductMessage::Create},
|
||||
{179, GraphicProductMessage::Create},
|
||||
{193, GraphicProductMessage::Create},
|
||||
{195, GraphicProductMessage::Create},
|
||||
{196, GraphicProductMessage::Create},
|
||||
{202, GraphicProductMessage::Create}};
|
||||
|
||||
std::shared_ptr<Level3Message> Level3MessageFactory::Create(std::istream& is)
|
||||
{
|
||||
Level3MessageHeader header;
|
||||
std::shared_ptr<Level3Message> message;
|
||||
|
||||
bool headerValid = header.Parse(is);
|
||||
bool messageValid = headerValid;
|
||||
|
||||
if (headerValid && create_.find(header.message_code()) == create_.end())
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< logPrefix_ << "Unknown message type: " << header.message_code();
|
||||
messageValid = false;
|
||||
}
|
||||
|
||||
if (messageValid)
|
||||
{
|
||||
int16_t messageCode = header.message_code();
|
||||
size_t dataSize = header.length_of_message() - Level3MessageHeader::SIZE;
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Found Message " << messageCode;
|
||||
|
||||
message = create_.at(messageCode)(std::move(header), is);
|
||||
}
|
||||
else if (headerValid)
|
||||
{
|
||||
// Seek to the end of the current message
|
||||
is.seekg(header.length_of_message() - Level3MessageHeader::SIZE,
|
||||
std::ios_base::cur);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
} // namespace rpg
|
||||
} // namespace wsr88d
|
||||
} // namespace scwx
|
||||
131
wxdata/source/scwx/wsr88d/rpg/tabular_product_message.cpp
Normal file
131
wxdata/source/scwx/wsr88d/rpg/tabular_product_message.cpp
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
#include <scwx/wsr88d/rpg/tabular_product_message.hpp>
|
||||
|
||||
#include <istream>
|
||||
#include <string>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace scwx
|
||||
{
|
||||
namespace wsr88d
|
||||
{
|
||||
namespace rpg
|
||||
{
|
||||
|
||||
static const std::string logPrefix_ =
|
||||
"[scwx::wsr88d::rpg::tabular_product_message] ";
|
||||
|
||||
class TabularProductMessageImpl
|
||||
{
|
||||
public:
|
||||
explicit TabularProductMessageImpl() :
|
||||
descriptionBlock_ {0}, tabularBlock_ {0}
|
||||
{
|
||||
}
|
||||
~TabularProductMessageImpl() = default;
|
||||
|
||||
bool LoadBlocks(std::istream& is);
|
||||
|
||||
std::shared_ptr<ProductDescriptionBlock> descriptionBlock_;
|
||||
std::shared_ptr<TabularAlphanumericBlock> tabularBlock_;
|
||||
};
|
||||
|
||||
TabularProductMessage::TabularProductMessage() :
|
||||
p(std::make_unique<TabularProductMessageImpl>())
|
||||
{
|
||||
}
|
||||
TabularProductMessage::~TabularProductMessage() = default;
|
||||
|
||||
TabularProductMessage::TabularProductMessage(TabularProductMessage&&) noexcept =
|
||||
default;
|
||||
TabularProductMessage&
|
||||
TabularProductMessage::operator=(TabularProductMessage&&) noexcept = default;
|
||||
|
||||
std::shared_ptr<ProductDescriptionBlock>
|
||||
TabularProductMessage::description_block() const
|
||||
{
|
||||
return p->descriptionBlock_;
|
||||
}
|
||||
|
||||
std::shared_ptr<TabularAlphanumericBlock>
|
||||
TabularProductMessage::tabular_block() const
|
||||
{
|
||||
return p->tabularBlock_;
|
||||
}
|
||||
|
||||
bool TabularProductMessage::Parse(std::istream& is)
|
||||
{
|
||||
bool dataValid = true;
|
||||
|
||||
const std::streampos dataStart = is.tellg();
|
||||
|
||||
p->descriptionBlock_ = std::make_shared<ProductDescriptionBlock>();
|
||||
dataValid = p->descriptionBlock_->Parse(is);
|
||||
|
||||
if (dataValid)
|
||||
{
|
||||
dataValid = p->LoadBlocks(is);
|
||||
}
|
||||
|
||||
const std::streampos dataEnd = is.tellg();
|
||||
if (!ValidateMessage(is, dataEnd - dataStart))
|
||||
{
|
||||
dataValid = false;
|
||||
}
|
||||
|
||||
return dataValid;
|
||||
}
|
||||
|
||||
bool TabularProductMessageImpl::LoadBlocks(std::istream& is)
|
||||
{
|
||||
constexpr bool skipTabularHeader = true;
|
||||
|
||||
bool tabularValid = true;
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Loading Blocks";
|
||||
|
||||
std::streampos offsetBasePos = is.tellg();
|
||||
|
||||
constexpr size_t offsetBase =
|
||||
Level3MessageHeader::SIZE + ProductDescriptionBlock::SIZE;
|
||||
|
||||
size_t offsetToTabular = descriptionBlock_->offset_to_symbology() * 2u;
|
||||
|
||||
if (offsetToTabular >= offsetBase)
|
||||
{
|
||||
tabularBlock_ = std::make_shared<TabularAlphanumericBlock>();
|
||||
|
||||
is.seekg(offsetToTabular - offsetBase, std::ios_base::cur);
|
||||
tabularValid = tabularBlock_->Parse(is, skipTabularHeader);
|
||||
is.seekg(offsetBasePos, std::ios_base::beg);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< logPrefix_ << "Tabular alphanumeric block valid: " << tabularValid;
|
||||
|
||||
if (!tabularValid)
|
||||
{
|
||||
tabularBlock_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return tabularValid;
|
||||
}
|
||||
|
||||
std::shared_ptr<TabularProductMessage>
|
||||
TabularProductMessage::Create(Level3MessageHeader&& header, std::istream& is)
|
||||
{
|
||||
std::shared_ptr<TabularProductMessage> message =
|
||||
std::make_shared<TabularProductMessage>();
|
||||
message->set_header(std::move(header));
|
||||
|
||||
if (!message->Parse(is))
|
||||
{
|
||||
message.reset();
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
} // namespace rpg
|
||||
} // namespace wsr88d
|
||||
} // namespace scwx
|
||||
Loading…
Add table
Add a link
Reference in a new issue