mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 04:30:05 +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 | ||||
| 
 | ||||
| #include <scwx/wsr88d/rpg/level3_message_header.hpp> | ||||
| #include <scwx/wsr88d/rpg/product_symbology_block.hpp> | ||||
| #include <scwx/wsr88d/rpg/level3_message.hpp> | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <string> | ||||
|  | @ -25,8 +24,7 @@ public: | |||
|    Level3File(Level3File&&) noexcept; | ||||
|    Level3File& operator=(Level3File&&) noexcept; | ||||
| 
 | ||||
|    std::shared_ptr<rpg::Level3MessageHeader>   message_header() const; | ||||
|    std::shared_ptr<rpg::ProductSymbologyBlock> product_symbology_block() const; | ||||
|    std::shared_ptr<rpg::Level3Message> message() const; | ||||
| 
 | ||||
|    bool LoadFile(const std::string& filename); | ||||
|    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/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
 | ||||
|  | @ -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/generic_data_packet.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/level3_message.hpp | ||||
|                    include/scwx/wsr88d/rpg/level3_message_factory.hpp | ||||
|                    include/scwx/wsr88d/rpg/level3_message_header.hpp | ||||
|                    include/scwx/wsr88d/rpg/linked_contour_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/storm_id_symbol_packet.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/unlinked_contour_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/generic_data_packet.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/level3_message.cpp | ||||
|                    source/scwx/wsr88d/rpg/level3_message_factory.cpp | ||||
|                    source/scwx/wsr88d/rpg/level3_message_header.cpp | ||||
|                    source/scwx/wsr88d/rpg/linked_contour_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/storm_id_symbol_packet.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/unlinked_contour_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