mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 08:10:06 +00:00 
			
		
		
		
	Parse coded information from text product content
This commit is contained in:
		
							parent
							
								
									8f3baaa7c3
								
							
						
					
					
						commit
						56cda08b0d
					
				
					 5 changed files with 115 additions and 9 deletions
				
			
		|  | @ -3,6 +3,7 @@ | |||
| #include <scwx/common/geographic.hpp> | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <optional> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
|  | @ -32,7 +33,10 @@ public: | |||
| 
 | ||||
|    std::vector<common::Coordinate> coordinates() const; | ||||
| 
 | ||||
|    bool Parse(const StringRange& lines, const std::string& wfo = ""); | ||||
|    bool Parse(const StringRange& lines, const std::string& wfo = {}); | ||||
| 
 | ||||
|    static std::optional<CodedLocation> Create(const StringRange& lines, | ||||
|                                               const std::string& wfo = {}); | ||||
| 
 | ||||
| private: | ||||
|    std::unique_ptr<CodedLocationImpl> p; | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ | |||
| 
 | ||||
| #include <chrono> | ||||
| #include <memory> | ||||
| #include <optional> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
|  | @ -36,7 +37,10 @@ public: | |||
|    uint8_t                                     speed() const; | ||||
|    std::vector<common::Coordinate>             coordinates() const; | ||||
| 
 | ||||
|    bool Parse(const StringRange& lines, const std::string& wfo = ""); | ||||
|    bool Parse(const StringRange& lines, const std::string& wfo = {}); | ||||
| 
 | ||||
|    static std::optional<CodedTimeMotionLocation> | ||||
|    Create(const StringRange& lines, const std::string& wfo = {}); | ||||
| 
 | ||||
| private: | ||||
|    std::unique_ptr<CodedTimeMotionLocationImpl> p; | ||||
|  |  | |||
|  | @ -205,5 +205,18 @@ bool CodedLocation::Parse(const StringRange& lines, const std::string& wfo) | |||
|    return dataValid; | ||||
| } | ||||
| 
 | ||||
| std::optional<CodedLocation> CodedLocation::Create(const StringRange& lines, | ||||
|                                                    const std::string& wfo) | ||||
| { | ||||
|    std::optional<CodedLocation> location = std::make_optional<CodedLocation>(); | ||||
| 
 | ||||
|    if (!location->Parse(lines, wfo)) | ||||
|    { | ||||
|       location.reset(); | ||||
|    } | ||||
| 
 | ||||
|    return location; | ||||
| } | ||||
| 
 | ||||
| } // namespace awips
 | ||||
| } // namespace scwx
 | ||||
|  |  | |||
|  | @ -234,5 +234,20 @@ bool CodedTimeMotionLocation::Parse(const StringRange& lines, | |||
|    return dataValid; | ||||
| } | ||||
| 
 | ||||
| std::optional<CodedTimeMotionLocation> | ||||
| CodedTimeMotionLocation::Create(const StringRange& lines, | ||||
|                                 const std::string& wfo) | ||||
| { | ||||
|    std::optional<CodedTimeMotionLocation> motion = | ||||
|       std::make_optional<CodedTimeMotionLocation>(); | ||||
| 
 | ||||
|    if (!motion->Parse(lines, wfo)) | ||||
|    { | ||||
|       motion.reset(); | ||||
|    } | ||||
| 
 | ||||
|    return motion; | ||||
| } | ||||
| 
 | ||||
| } // namespace awips
 | ||||
| } // namespace scwx
 | ||||
|  |  | |||
|  | @ -1,4 +1,6 @@ | |||
| #include <scwx/awips/text_product_message.hpp> | ||||
| #include <scwx/awips/coded_location.hpp> | ||||
| #include <scwx/awips/coded_time_motion_location.hpp> | ||||
| #include <scwx/awips/pvtec.hpp> | ||||
| #include <scwx/common/characters.hpp> | ||||
| #include <scwx/util/streams.hpp> | ||||
|  | @ -59,10 +61,15 @@ struct SegmentHeader | |||
| 
 | ||||
| struct Segment | ||||
| { | ||||
|    std::optional<SegmentHeader> header_; | ||||
|    std::vector<std::string>     productContent_; | ||||
|    std::optional<SegmentHeader>           header_; | ||||
|    std::vector<std::string>               productContent_; | ||||
|    std::optional<CodedLocation>           codedLocation_; | ||||
|    std::optional<CodedTimeMotionLocation> codedMotion_; | ||||
| 
 | ||||
|    Segment() : header_ {}, productContent_ {} {} | ||||
|    Segment() : | ||||
|        header_ {}, productContent_ {}, codedLocation_ {}, codedMotion_ {} | ||||
|    { | ||||
|    } | ||||
| 
 | ||||
|    Segment(const Segment&) = delete; | ||||
|    Segment& operator=(const Segment&) = delete; | ||||
|  | @ -71,9 +78,11 @@ struct Segment | |||
|    Segment& operator=(Segment&&) noexcept = default; | ||||
| }; | ||||
| 
 | ||||
| static void ParseCodedInformation(std::shared_ptr<Segment> segment, | ||||
|                                   const std::string&       wfo); | ||||
| static std::vector<std::string>     ParseProductContent(std::istream& is); | ||||
| void                                SkipBlankLines(std::istream& is); | ||||
| bool                                TryParseEndOfProduct(std::istream& is); | ||||
| static void                         SkipBlankLines(std::istream& is); | ||||
| static bool                         TryParseEndOfProduct(std::istream& is); | ||||
| static std::vector<std::string>     TryParseMndHeader(std::istream& is); | ||||
| static std::vector<std::string>     TryParseOverviewBlock(std::istream& is); | ||||
| static std::optional<SegmentHeader> TryParseSegmentHeader(std::istream& is); | ||||
|  | @ -156,6 +165,8 @@ bool TextProductMessage::Parse(std::istream& is) | |||
|       segment->productContent_ = ParseProductContent(is); | ||||
|       SkipBlankLines(is); | ||||
| 
 | ||||
|       ParseCodedInformation(segment, p->wmoHeader_->icao()); | ||||
| 
 | ||||
|       if (segment->header_.has_value() || !segment->productContent_.empty()) | ||||
|       { | ||||
|          p->segments_.push_back(std::move(segment)); | ||||
|  | @ -165,6 +176,58 @@ bool TextProductMessage::Parse(std::istream& is) | |||
|    return dataValid; | ||||
| } | ||||
| 
 | ||||
| void ParseCodedInformation(std::shared_ptr<Segment> segment, | ||||
|                            const std::string&       wfo) | ||||
| { | ||||
|    typedef std::vector<std::string>::const_iterator StringIterator; | ||||
| 
 | ||||
|    std::vector<std::string>& productContent = segment->productContent_; | ||||
| 
 | ||||
|    StringIterator codedLocationBegin = productContent.cend(); | ||||
|    StringIterator codedLocationEnd   = productContent.cend(); | ||||
|    StringIterator codedMotionBegin   = productContent.cend(); | ||||
|    StringIterator codedMotionEnd     = productContent.cend(); | ||||
| 
 | ||||
|    for (auto it = productContent.cbegin(); it != productContent.cend(); ++it) | ||||
|    { | ||||
|       if (codedLocationBegin == productContent.cend() && | ||||
|           it->starts_with("LAT...LON")) | ||||
|       { | ||||
|          codedLocationBegin = it; | ||||
|       } | ||||
|       else if (codedLocationBegin != productContent.cend() && | ||||
|                codedLocationEnd == productContent.cend() && | ||||
|                !it->starts_with(" ") /* Continuation line */) | ||||
|       { | ||||
|          codedLocationEnd = it; | ||||
|       } | ||||
| 
 | ||||
|       if (codedMotionBegin == productContent.cend() && | ||||
|           it->starts_with("TIME...MOT...LOC")) | ||||
|       { | ||||
|          codedMotionBegin = it; | ||||
|       } | ||||
|       else if (codedMotionBegin != productContent.cend() && | ||||
|                codedMotionEnd == productContent.cend() && | ||||
|                !it->starts_with(" ") /* Continuation line */) | ||||
|       { | ||||
|          codedMotionEnd = it; | ||||
|       } | ||||
|    } | ||||
| 
 | ||||
|    if (codedLocationBegin != productContent.cend()) | ||||
|    { | ||||
|       segment->codedLocation_ = | ||||
|          CodedLocation::Create({codedLocationBegin, codedLocationEnd}, wfo); | ||||
|    } | ||||
| 
 | ||||
|    if (codedMotionBegin != productContent.cend()) | ||||
|    { | ||||
|       segment->codedMotion_ = CodedTimeMotionLocation::Create( | ||||
|          {codedMotionBegin, codedMotionEnd}, wfo); | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| std::vector<std::string> ParseProductContent(std::istream& is) | ||||
| { | ||||
|    std::vector<std::string> productContent; | ||||
|  | @ -367,8 +430,10 @@ std::optional<Vtec> TryParseVtecString(std::istream& is) | |||
| 
 | ||||
|    if (std::regex_search(line, rePVtecString)) | ||||
|    { | ||||
|       vtec = Vtec(); | ||||
|       vtec->pVtec_.Parse(line); | ||||
|       bool vtecValid; | ||||
| 
 | ||||
|       vtec      = Vtec(); | ||||
|       vtecValid = vtec->pVtec_.Parse(line); | ||||
| 
 | ||||
|       isBegin = is.tellg(); | ||||
| 
 | ||||
|  | @ -384,6 +449,11 @@ std::optional<Vtec> TryParseVtecString(std::istream& is) | |||
|          // the line
 | ||||
|          is.seekg(isBegin, std::ios_base::beg); | ||||
|       } | ||||
| 
 | ||||
|       if (!vtecValid) | ||||
|       { | ||||
|          vtec.reset(); | ||||
|       } | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat