diff --git a/wxdata/source/scwx/awips/text_product_message.cpp b/wxdata/source/scwx/awips/text_product_message.cpp index 54ce7e25..3b571d83 100644 --- a/wxdata/source/scwx/awips/text_product_message.cpp +++ b/wxdata/source/scwx/awips/text_product_message.cpp @@ -11,9 +11,7 @@ #include #include -namespace scwx -{ -namespace awips +namespace scwx::awips { static const std::string logPrefix_ = "scwx::awips::text_product_message"; @@ -49,6 +47,11 @@ public: { } ~TextProductMessageImpl() = default; + + TextProductMessageImpl(const TextProductMessageImpl&) = delete; + TextProductMessageImpl& operator=(const TextProductMessageImpl&) = delete; + TextProductMessageImpl(const TextProductMessageImpl&&) = delete; + TextProductMessageImpl& operator=(const TextProductMessageImpl&&) = delete; std::string messageContent_; std::shared_ptr wmoHeader_; @@ -232,7 +235,7 @@ bool TextProductMessage::Parse(std::istream& is) if (i == 0) { - if (is.peek() != '\r') + if (is.peek() != '\r' && is.peek() != '\n') { segment->header_ = TryParseSegmentHeader(is); } @@ -318,8 +321,8 @@ bool TextProductMessage::Parse(std::istream& is) return dataValid; } -void ParseCodedInformation(std::shared_ptr segment, - const std::string& wfo) +void ParseCodedInformation(const std::shared_ptr& segment, + const std::string& wfo) { typedef std::vector::const_iterator StringIterator; @@ -352,8 +355,8 @@ void ParseCodedInformation(std::shared_ptr segment, codedLocationEnd = it; } - else if (codedMotionBegin == productContent.cend() && - it->starts_with("TIME...MOT...LOC")) + if (codedMotionBegin == productContent.cend() && + it->starts_with("TIME...MOT...LOC")) { codedMotionBegin = it; } @@ -366,8 +369,7 @@ void ParseCodedInformation(std::shared_ptr segment, codedMotionEnd = it; } - else if (!segment->observed_ && - it->find("...OBSERVED") != std::string::npos) + if (!segment->observed_ && it->find("...OBSERVED") != std::string::npos) { segment->observed_ = true; } @@ -378,6 +380,8 @@ void ParseCodedInformation(std::shared_ptr segment, segment->tornadoPossible_ = true; } + // Assignment of an iterator permitted + // NOLINTBEGIN(bugprone-assignment-in-if-condition) else if (segment->threatCategory_ == ibw::ThreatCategory::Base && (threatTagIt = std::find_if(kThreatCategoryTags.cbegin(), kThreatCategoryTags.cend(), @@ -385,6 +389,7 @@ void ParseCodedInformation(std::shared_ptr segment, return it->starts_with(tag); })) != kThreatCategoryTags.cend() && it->length() > threatTagIt->length()) + // NOLINTEND(bugprone-assignment-in-if-condition) { const std::string threatCategoryName = it->substr(threatTagIt->length()); @@ -458,7 +463,7 @@ void SkipBlankLines(std::istream& is) { std::string line; - while (is.peek() == '\r') + while (is.peek() == '\r' || is.peek() == '\n') { util::getline(is, line); } @@ -513,7 +518,7 @@ std::vector TryParseMndHeader(std::istream& is) std::string line; std::streampos isBegin = is.tellg(); - while (!is.eof() && is.peek() != '\r') + while (!is.eof() && is.peek() != '\r' && is.peek() != '\n') { util::getline(is, line); mndHeader.push_back(line); @@ -546,7 +551,7 @@ std::vector TryParseOverviewBlock(std::istream& is) if (is.peek() == '.') { - while (!is.eof() && is.peek() != '\r') + while (!is.eof() && is.peek() != '\r' && is.peek() != '\n') { util::getline(is, line); overviewBlock.push_back(line); @@ -576,7 +581,7 @@ std::optional TryParseSegmentHeader(std::istream& is) header->ugcString_.push_back(line); // If UGC is multi-line, continue parsing - while (!is.eof() && is.peek() != '\r' && + while (!is.eof() && is.peek() != '\r' && is.peek() != '\n' && !RE2::PartialMatch(line, *reUgcExpiration)) { util::getline(is, line); @@ -595,7 +600,7 @@ std::optional TryParseSegmentHeader(std::istream& is) header->vtecString_.push_back(std::move(*vtec)); } - while (!is.eof() && is.peek() != '\r') + while (!is.eof() && is.peek() != '\r' && is.peek() != '\n') { util::getline(is, line); if (!RE2::PartialMatch(line, *reDateTimeString)) @@ -640,10 +645,8 @@ std::optional TryParseVtecString(std::istream& is) if (RE2::PartialMatch(line, *rePVtecString)) { - bool vtecValid; - - vtec = Vtec(); - vtecValid = vtec->pVtec_.Parse(line); + vtec = Vtec(); + bool vtecValid = vtec->pVtec_.Parse(line); isBegin = is.tellg(); @@ -687,5 +690,4 @@ std::shared_ptr TextProductMessage::Create(std::istream& is) return message; } -} // namespace awips -} // namespace scwx +} // namespace scwx::awips diff --git a/wxdata/source/scwx/util/streams.cpp b/wxdata/source/scwx/util/streams.cpp index 9e094f9b..6374ed35 100644 --- a/wxdata/source/scwx/util/streams.cpp +++ b/wxdata/source/scwx/util/streams.cpp @@ -1,8 +1,7 @@ #include +#include -namespace scwx -{ -namespace util +namespace scwx::util { std::istream& getline(std::istream& is, std::string& t) @@ -17,7 +16,8 @@ std::istream& getline(std::istream& is, std::string& t) int c = sb->sbumpc(); switch (c) { - case '\n': return is; + case '\n': + return is; case '\r': while (sb->sgetc() == '\r') @@ -30,6 +30,10 @@ std::istream& getline(std::istream& is, std::string& t) } return is; + case common::Characters::ETX: + sb->sungetc(); + return is; + case std::streambuf::traits_type::eof(): if (t.empty()) { @@ -37,10 +41,10 @@ std::istream& getline(std::istream& is, std::string& t) } return is; - default: t += static_cast(c); + default: + t += static_cast(c); } } } -} // namespace util -} // namespace scwx +} // namespace scwx::util