mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 05: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,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
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat