mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 07:00: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,7 +1,6 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <scwx/wsr88d/rpg/level3_message_header.hpp> | #include <scwx/wsr88d/rpg/level3_message.hpp> | ||||||
| #include <scwx/wsr88d/rpg/product_symbology_block.hpp> |  | ||||||
| 
 | 
 | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <string> | #include <string> | ||||||
|  | @ -25,8 +24,7 @@ public: | ||||||
|    Level3File(Level3File&&) noexcept; |    Level3File(Level3File&&) noexcept; | ||||||
|    Level3File& operator=(Level3File&&) noexcept; |    Level3File& operator=(Level3File&&) noexcept; | ||||||
| 
 | 
 | ||||||
|    std::shared_ptr<rpg::Level3MessageHeader>   message_header() const; |    std::shared_ptr<rpg::Level3Message> message() const; | ||||||
|    std::shared_ptr<rpg::ProductSymbologyBlock> product_symbology_block() const; |  | ||||||
| 
 | 
 | ||||||
|    bool LoadFile(const std::string& filename); |    bool LoadFile(const std::string& filename); | ||||||
|    bool LoadData(std::istream& is); |    bool LoadData(std::istream& is); | ||||||
|  |  | ||||||
							
								
								
									
										49
									
								
								wxdata/include/scwx/wsr88d/rpg/graphic_product_message.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								wxdata/include/scwx/wsr88d/rpg/graphic_product_message.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <scwx/wsr88d/rpg/graphic_alphanumeric_block.hpp> | ||||||
|  | #include <scwx/wsr88d/rpg/level3_message.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 <cstdint> | ||||||
|  | #include <memory> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace wsr88d | ||||||
|  | { | ||||||
|  | namespace rpg | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class GraphicProductMessageImpl; | ||||||
|  | 
 | ||||||
|  | class GraphicProductMessage : public Level3Message | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit GraphicProductMessage(); | ||||||
|  |    ~GraphicProductMessage(); | ||||||
|  | 
 | ||||||
|  |    GraphicProductMessage(const GraphicProductMessage&) = delete; | ||||||
|  |    GraphicProductMessage& operator=(const GraphicProductMessage&) = delete; | ||||||
|  | 
 | ||||||
|  |    GraphicProductMessage(GraphicProductMessage&&) noexcept; | ||||||
|  |    GraphicProductMessage& operator=(GraphicProductMessage&&) noexcept; | ||||||
|  | 
 | ||||||
|  |    std::shared_ptr<ProductDescriptionBlock>  description_block() const; | ||||||
|  |    std::shared_ptr<ProductSymbologyBlock>    symbology_block() const; | ||||||
|  |    std::shared_ptr<GraphicAlphanumericBlock> graphic_block() const; | ||||||
|  |    std::shared_ptr<TabularAlphanumericBlock> tabular_block() const; | ||||||
|  | 
 | ||||||
|  |    bool Parse(std::istream& is) override; | ||||||
|  | 
 | ||||||
|  |    static std::shared_ptr<GraphicProductMessage> | ||||||
|  |    Create(Level3MessageHeader&& header, std::istream& is); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    std::unique_ptr<GraphicProductMessageImpl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace rpg
 | ||||||
|  | } // namespace wsr88d
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										41
									
								
								wxdata/include/scwx/wsr88d/rpg/level3_message.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								wxdata/include/scwx/wsr88d/rpg/level3_message.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <scwx/wsr88d/rpg/level3_message_header.hpp> | ||||||
|  | #include <scwx/wsr88d/message.hpp> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace wsr88d | ||||||
|  | { | ||||||
|  | namespace rpg | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class Level3MessageImpl; | ||||||
|  | 
 | ||||||
|  | class Level3Message : public Message | ||||||
|  | { | ||||||
|  | protected: | ||||||
|  |    explicit Level3Message(); | ||||||
|  | 
 | ||||||
|  |    Level3Message(const Level3Message&) = delete; | ||||||
|  |    Level3Message& operator=(const Level3Message&) = delete; | ||||||
|  | 
 | ||||||
|  |    Level3Message(Level3Message&&) noexcept; | ||||||
|  |    Level3Message& operator=(Level3Message&&) noexcept; | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |    virtual ~Level3Message(); | ||||||
|  | 
 | ||||||
|  |    size_t data_size() const override; | ||||||
|  | 
 | ||||||
|  |    const Level3MessageHeader& header() const; | ||||||
|  | 
 | ||||||
|  |    void set_header(Level3MessageHeader&& header); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    std::unique_ptr<Level3MessageImpl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace rpg
 | ||||||
|  | } // namespace wsr88d
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										30
									
								
								wxdata/include/scwx/wsr88d/rpg/level3_message_factory.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								wxdata/include/scwx/wsr88d/rpg/level3_message_factory.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <scwx/wsr88d/rpg/level3_message.hpp> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace wsr88d | ||||||
|  | { | ||||||
|  | namespace rpg | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class Level3MessageFactory | ||||||
|  | { | ||||||
|  | private: | ||||||
|  |    explicit Level3MessageFactory() = delete; | ||||||
|  |    ~Level3MessageFactory()         = delete; | ||||||
|  | 
 | ||||||
|  |    Level3MessageFactory(const Level3MessageFactory&) = delete; | ||||||
|  |    Level3MessageFactory& operator=(const Level3MessageFactory&) = delete; | ||||||
|  | 
 | ||||||
|  |    Level3MessageFactory(Level3MessageFactory&&) noexcept = delete; | ||||||
|  |    Level3MessageFactory& operator=(Level3MessageFactory&&) noexcept = delete; | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |    static std::shared_ptr<Level3Message> Create(std::istream& is); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace rpg
 | ||||||
|  | } // namespace wsr88d
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										45
									
								
								wxdata/include/scwx/wsr88d/rpg/tabular_product_message.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								wxdata/include/scwx/wsr88d/rpg/tabular_product_message.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <scwx/wsr88d/rpg/level3_message.hpp> | ||||||
|  | #include <scwx/wsr88d/rpg/product_description_block.hpp> | ||||||
|  | #include <scwx/wsr88d/rpg/tabular_alphanumeric_block.hpp> | ||||||
|  | 
 | ||||||
|  | #include <cstdint> | ||||||
|  | #include <memory> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace wsr88d | ||||||
|  | { | ||||||
|  | namespace rpg | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class TabularProductMessageImpl; | ||||||
|  | 
 | ||||||
|  | class TabularProductMessage : public Level3Message | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit TabularProductMessage(); | ||||||
|  |    ~TabularProductMessage(); | ||||||
|  | 
 | ||||||
|  |    TabularProductMessage(const TabularProductMessage&) = delete; | ||||||
|  |    TabularProductMessage& operator=(const TabularProductMessage&) = delete; | ||||||
|  | 
 | ||||||
|  |    TabularProductMessage(TabularProductMessage&&) noexcept; | ||||||
|  |    TabularProductMessage& operator=(TabularProductMessage&&) noexcept; | ||||||
|  | 
 | ||||||
|  |    std::shared_ptr<ProductDescriptionBlock>  description_block() const; | ||||||
|  |    std::shared_ptr<TabularAlphanumericBlock> tabular_block() const; | ||||||
|  | 
 | ||||||
|  |    bool Parse(std::istream& is) override; | ||||||
|  | 
 | ||||||
|  |    static std::shared_ptr<TabularProductMessage> | ||||||
|  |    Create(Level3MessageHeader&& header, std::istream& is); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    std::unique_ptr<TabularProductMessageImpl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace rpg
 | ||||||
|  | } // namespace wsr88d
 | ||||||
|  | } // namespace scwx
 | ||||||
|  | @ -1,20 +1,12 @@ | ||||||
| #include <scwx/wsr88d/level3_file.hpp> | #include <scwx/wsr88d/level3_file.hpp> | ||||||
| #include <scwx/wsr88d/rpg/ccb_header.hpp> | #include <scwx/wsr88d/rpg/ccb_header.hpp> | ||||||
| #include <scwx/wsr88d/rpg/graphic_alphanumeric_block.hpp> | #include <scwx/wsr88d/rpg/level3_message_factory.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/wmo_header.hpp> | #include <scwx/wsr88d/rpg/wmo_header.hpp> | ||||||
| #include <scwx/util/rangebuf.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> | ||||||
| #include <boost/iostreams/filter/bzip2.hpp> |  | ||||||
| #include <boost/iostreams/filter/zlib.hpp> | #include <boost/iostreams/filter/zlib.hpp> | ||||||
| #include <boost/log/trivial.hpp> | #include <boost/log/trivial.hpp> | ||||||
| 
 | 
 | ||||||
|  | @ -25,33 +17,20 @@ 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: | ||||||
|    explicit Level3FileImpl() : |    explicit Level3FileImpl() : | ||||||
|        wmoHeader_ {}, |        wmoHeader_ {}, ccbHeader_ {}, innerHeader_ {}, message_ {} {}; | ||||||
|        ccbHeader_ {}, |  | ||||||
|        messageHeader_ {}, |  | ||||||
|        descriptionBlock_ {}, |  | ||||||
|        symbologyBlock_ {}, |  | ||||||
|        graphicBlock_ {}, |  | ||||||
|        tabularBlock_ {} {}; |  | ||||||
|    ~Level3FileImpl() = default; |    ~Level3FileImpl() = default; | ||||||
| 
 | 
 | ||||||
|    bool DecompressFile(std::istream& is, std::stringstream& ss); |    bool DecompressFile(std::istream& is, std::stringstream& ss); | ||||||
|    bool LoadFileData(std::istream& is); |    bool LoadFileData(std::istream& is); | ||||||
|    bool LoadBlocks(std::istream& is); |  | ||||||
| 
 | 
 | ||||||
|    std::shared_ptr<rpg::WmoHeader>     wmoHeader_; |    std::shared_ptr<rpg::WmoHeader>     wmoHeader_; | ||||||
|    std::shared_ptr<rpg::CcbHeader>     ccbHeader_; |    std::shared_ptr<rpg::CcbHeader>     ccbHeader_; | ||||||
|    std::shared_ptr<rpg::WmoHeader>     innerHeader_; |    std::shared_ptr<rpg::WmoHeader>     innerHeader_; | ||||||
|    std::shared_ptr<rpg::Level3MessageHeader>      messageHeader_; |    std::shared_ptr<rpg::Level3Message> message_; | ||||||
|    std::shared_ptr<rpg::ProductDescriptionBlock>  descriptionBlock_; |  | ||||||
|    std::shared_ptr<rpg::ProductSymbologyBlock>    symbologyBlock_; |  | ||||||
|    std::shared_ptr<rpg::GraphicAlphanumericBlock> graphicBlock_; |  | ||||||
|    std::shared_ptr<rpg::TabularAlphanumericBlock> tabularBlock_; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| Level3File::Level3File() : p(std::make_unique<Level3FileImpl>()) {} | Level3File::Level3File() : p(std::make_unique<Level3FileImpl>()) {} | ||||||
|  | @ -60,15 +39,9 @@ Level3File::~Level3File() = default; | ||||||
| Level3File::Level3File(Level3File&&) noexcept = default; | Level3File::Level3File(Level3File&&) noexcept = default; | ||||||
| Level3File& Level3File::operator=(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_; |    return p->message_; | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::shared_ptr<rpg::ProductSymbologyBlock> |  | ||||||
| Level3File::product_symbology_block() const |  | ||||||
| { |  | ||||||
|    return p->symbologyBlock_; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool Level3File::LoadFile(const std::string& filename) | 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) | bool Level3FileImpl::LoadFileData(std::istream& is) | ||||||
| { | { | ||||||
|    messageHeader_ = std::make_shared<rpg::Level3MessageHeader>(); |    message_ = rpg::Level3MessageFactory::Create(is); | ||||||
| 
 | 
 | ||||||
|    bool dataValid = messageHeader_->Parse(is); |    return (message_ != nullptr); | ||||||
| 
 |  | ||||||
|    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); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace wsr88d
 | } // 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
 | ||||||
|  | @ -53,7 +53,10 @@ set(HDR_WSR88D_RPG include/scwx/wsr88d/rpg/ccb_header.hpp | ||||||
|                    include/scwx/wsr88d/rpg/digital_radial_data_array_packet.hpp |                    include/scwx/wsr88d/rpg/digital_radial_data_array_packet.hpp | ||||||
|                    include/scwx/wsr88d/rpg/generic_data_packet.hpp |                    include/scwx/wsr88d/rpg/generic_data_packet.hpp | ||||||
|                    include/scwx/wsr88d/rpg/graphic_alphanumeric_block.hpp |                    include/scwx/wsr88d/rpg/graphic_alphanumeric_block.hpp | ||||||
|  |                    include/scwx/wsr88d/rpg/graphic_product_message.hpp | ||||||
|                    include/scwx/wsr88d/rpg/hda_hail_symbol_packet.hpp |                    include/scwx/wsr88d/rpg/hda_hail_symbol_packet.hpp | ||||||
|  |                    include/scwx/wsr88d/rpg/level3_message.hpp | ||||||
|  |                    include/scwx/wsr88d/rpg/level3_message_factory.hpp | ||||||
|                    include/scwx/wsr88d/rpg/level3_message_header.hpp |                    include/scwx/wsr88d/rpg/level3_message_header.hpp | ||||||
|                    include/scwx/wsr88d/rpg/linked_contour_vector_packet.hpp |                    include/scwx/wsr88d/rpg/linked_contour_vector_packet.hpp | ||||||
|                    include/scwx/wsr88d/rpg/linked_vector_packet.hpp |                    include/scwx/wsr88d/rpg/linked_vector_packet.hpp | ||||||
|  | @ -73,6 +76,7 @@ set(HDR_WSR88D_RPG include/scwx/wsr88d/rpg/ccb_header.hpp | ||||||
|                    include/scwx/wsr88d/rpg/sti_circle_symbol_packet.hpp |                    include/scwx/wsr88d/rpg/sti_circle_symbol_packet.hpp | ||||||
|                    include/scwx/wsr88d/rpg/storm_id_symbol_packet.hpp |                    include/scwx/wsr88d/rpg/storm_id_symbol_packet.hpp | ||||||
|                    include/scwx/wsr88d/rpg/tabular_alphanumeric_block.hpp |                    include/scwx/wsr88d/rpg/tabular_alphanumeric_block.hpp | ||||||
|  |                    include/scwx/wsr88d/rpg/tabular_product_message.hpp | ||||||
|                    include/scwx/wsr88d/rpg/text_and_special_symbol_packet.hpp |                    include/scwx/wsr88d/rpg/text_and_special_symbol_packet.hpp | ||||||
|                    include/scwx/wsr88d/rpg/unlinked_contour_vector_packet.hpp |                    include/scwx/wsr88d/rpg/unlinked_contour_vector_packet.hpp | ||||||
|                    include/scwx/wsr88d/rpg/unlinked_vector_packet.hpp |                    include/scwx/wsr88d/rpg/unlinked_vector_packet.hpp | ||||||
|  | @ -86,7 +90,10 @@ set(SRC_WSR88D_RPG source/scwx/wsr88d/rpg/ccb_header.cpp | ||||||
|                    source/scwx/wsr88d/rpg/digital_radial_data_array_packet.cpp |                    source/scwx/wsr88d/rpg/digital_radial_data_array_packet.cpp | ||||||
|                    source/scwx/wsr88d/rpg/generic_data_packet.cpp |                    source/scwx/wsr88d/rpg/generic_data_packet.cpp | ||||||
|                    source/scwx/wsr88d/rpg/graphic_alphanumeric_block.cpp |                    source/scwx/wsr88d/rpg/graphic_alphanumeric_block.cpp | ||||||
|  |                    source/scwx/wsr88d/rpg/graphic_product_message.cpp | ||||||
|                    source/scwx/wsr88d/rpg/hda_hail_symbol_packet.cpp |                    source/scwx/wsr88d/rpg/hda_hail_symbol_packet.cpp | ||||||
|  |                    source/scwx/wsr88d/rpg/level3_message.cpp | ||||||
|  |                    source/scwx/wsr88d/rpg/level3_message_factory.cpp | ||||||
|                    source/scwx/wsr88d/rpg/level3_message_header.cpp |                    source/scwx/wsr88d/rpg/level3_message_header.cpp | ||||||
|                    source/scwx/wsr88d/rpg/linked_contour_vector_packet.cpp |                    source/scwx/wsr88d/rpg/linked_contour_vector_packet.cpp | ||||||
|                    source/scwx/wsr88d/rpg/linked_vector_packet.cpp |                    source/scwx/wsr88d/rpg/linked_vector_packet.cpp | ||||||
|  | @ -106,6 +113,7 @@ set(SRC_WSR88D_RPG source/scwx/wsr88d/rpg/ccb_header.cpp | ||||||
|                    source/scwx/wsr88d/rpg/sti_circle_symbol_packet.cpp |                    source/scwx/wsr88d/rpg/sti_circle_symbol_packet.cpp | ||||||
|                    source/scwx/wsr88d/rpg/storm_id_symbol_packet.cpp |                    source/scwx/wsr88d/rpg/storm_id_symbol_packet.cpp | ||||||
|                    source/scwx/wsr88d/rpg/tabular_alphanumeric_block.cpp |                    source/scwx/wsr88d/rpg/tabular_alphanumeric_block.cpp | ||||||
|  |                    source/scwx/wsr88d/rpg/tabular_product_message.cpp | ||||||
|                    source/scwx/wsr88d/rpg/text_and_special_symbol_packet.cpp |                    source/scwx/wsr88d/rpg/text_and_special_symbol_packet.cpp | ||||||
|                    source/scwx/wsr88d/rpg/unlinked_contour_vector_packet.cpp |                    source/scwx/wsr88d/rpg/unlinked_contour_vector_packet.cpp | ||||||
|                    source/scwx/wsr88d/rpg/unlinked_vector_packet.cpp |                    source/scwx/wsr88d/rpg/unlinked_vector_packet.cpp | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat