mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 03:00: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 <scwx/common/geographic.hpp> | ||||||
| 
 | 
 | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include <optional> | ||||||
| #include <string> | #include <string> | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
|  | @ -32,7 +33,10 @@ public: | ||||||
| 
 | 
 | ||||||
|    std::vector<common::Coordinate> coordinates() 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<CodedLocation> Create(const StringRange& lines, | ||||||
|  |                                               const std::string& wfo = {}); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|    std::unique_ptr<CodedLocationImpl> p; |    std::unique_ptr<CodedLocationImpl> p; | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <chrono> | #include <chrono> | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include <optional> | ||||||
| #include <string> | #include <string> | ||||||
| #include <vector> | #include <vector> | ||||||
| 
 | 
 | ||||||
|  | @ -36,7 +37,10 @@ public: | ||||||
|    uint8_t                                     speed() const; |    uint8_t                                     speed() const; | ||||||
|    std::vector<common::Coordinate>             coordinates() 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: | private: | ||||||
|    std::unique_ptr<CodedTimeMotionLocationImpl> p; |    std::unique_ptr<CodedTimeMotionLocationImpl> p; | ||||||
|  |  | ||||||
|  | @ -205,5 +205,18 @@ bool CodedLocation::Parse(const StringRange& lines, const std::string& wfo) | ||||||
|    return dataValid; |    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 awips
 | ||||||
| } // namespace scwx
 | } // namespace scwx
 | ||||||
|  |  | ||||||
|  | @ -234,5 +234,20 @@ bool CodedTimeMotionLocation::Parse(const StringRange& lines, | ||||||
|    return dataValid; |    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 awips
 | ||||||
| } // namespace scwx
 | } // namespace scwx
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,6 @@ | ||||||
| #include <scwx/awips/text_product_message.hpp> | #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/awips/pvtec.hpp> | ||||||
| #include <scwx/common/characters.hpp> | #include <scwx/common/characters.hpp> | ||||||
| #include <scwx/util/streams.hpp> | #include <scwx/util/streams.hpp> | ||||||
|  | @ -61,8 +63,13 @@ struct Segment | ||||||
| { | { | ||||||
|    std::optional<SegmentHeader>           header_; |    std::optional<SegmentHeader>           header_; | ||||||
|    std::vector<std::string>               productContent_; |    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(const Segment&) = delete; | ||||||
|    Segment& operator=(const Segment&) = delete; |    Segment& operator=(const Segment&) = delete; | ||||||
|  | @ -71,9 +78,11 @@ struct Segment | ||||||
|    Segment& operator=(Segment&&) noexcept = default; |    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); | static std::vector<std::string>     ParseProductContent(std::istream& is); | ||||||
| void                                SkipBlankLines(std::istream& is); | static void                         SkipBlankLines(std::istream& is); | ||||||
| bool                                TryParseEndOfProduct(std::istream& is); | static bool                         TryParseEndOfProduct(std::istream& is); | ||||||
| static std::vector<std::string>     TryParseMndHeader(std::istream& is); | static std::vector<std::string>     TryParseMndHeader(std::istream& is); | ||||||
| static std::vector<std::string>     TryParseOverviewBlock(std::istream& is); | static std::vector<std::string>     TryParseOverviewBlock(std::istream& is); | ||||||
| static std::optional<SegmentHeader> TryParseSegmentHeader(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); |       segment->productContent_ = ParseProductContent(is); | ||||||
|       SkipBlankLines(is); |       SkipBlankLines(is); | ||||||
| 
 | 
 | ||||||
|  |       ParseCodedInformation(segment, p->wmoHeader_->icao()); | ||||||
|  | 
 | ||||||
|       if (segment->header_.has_value() || !segment->productContent_.empty()) |       if (segment->header_.has_value() || !segment->productContent_.empty()) | ||||||
|       { |       { | ||||||
|          p->segments_.push_back(std::move(segment)); |          p->segments_.push_back(std::move(segment)); | ||||||
|  | @ -165,6 +176,58 @@ bool TextProductMessage::Parse(std::istream& is) | ||||||
|    return dataValid; |    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> ParseProductContent(std::istream& is) | ||||||
| { | { | ||||||
|    std::vector<std::string> productContent; |    std::vector<std::string> productContent; | ||||||
|  | @ -367,8 +430,10 @@ std::optional<Vtec> TryParseVtecString(std::istream& is) | ||||||
| 
 | 
 | ||||||
|    if (std::regex_search(line, rePVtecString)) |    if (std::regex_search(line, rePVtecString)) | ||||||
|    { |    { | ||||||
|  |       bool vtecValid; | ||||||
|  | 
 | ||||||
|       vtec      = Vtec(); |       vtec      = Vtec(); | ||||||
|       vtec->pVtec_.Parse(line); |       vtecValid = vtec->pVtec_.Parse(line); | ||||||
| 
 | 
 | ||||||
|       isBegin = is.tellg(); |       isBegin = is.tellg(); | ||||||
| 
 | 
 | ||||||
|  | @ -384,6 +449,11 @@ std::optional<Vtec> TryParseVtecString(std::istream& is) | ||||||
|          // the line
 |          // the line
 | ||||||
|          is.seekg(isBegin, std::ios_base::beg); |          is.seekg(isBegin, std::ios_base::beg); | ||||||
|       } |       } | ||||||
|  | 
 | ||||||
|  |       if (!vtecValid) | ||||||
|  |       { | ||||||
|  |          vtec.reset(); | ||||||
|  |       } | ||||||
|    } |    } | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat