diff --git a/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp b/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp index 1c743702..a2da6736 100644 --- a/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp @@ -40,6 +40,21 @@ public: TextEventManager::TextEventManager() : p(std::make_unique(this)) {} TextEventManager::~TextEventManager() = default; +size_t TextEventManager::message_count(const types::TextEventKey& key) const +{ + size_t messageCount = 0u; + + std::shared_lock lock(p->textEventMutex_); + + auto it = p->textEventMap_.find(key); + if (it != p->textEventMap_.cend()) + { + messageCount = it->second.size(); + } + + return messageCount; +} + std::vector> TextEventManager::message_list(const types::TextEventKey& key) const { diff --git a/scwx-qt/source/scwx/qt/manager/text_event_manager.hpp b/scwx-qt/source/scwx/qt/manager/text_event_manager.hpp index 97f313cb..8f9f7719 100644 --- a/scwx-qt/source/scwx/qt/manager/text_event_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/text_event_manager.hpp @@ -23,6 +23,7 @@ public: explicit TextEventManager(); ~TextEventManager(); + size_t message_count(const types::TextEventKey& key) const; std::vector> message_list(const types::TextEventKey& key) const; diff --git a/scwx-qt/source/scwx/qt/types/text_event_key.cpp b/scwx-qt/source/scwx/qt/types/text_event_key.cpp index cbf29baf..f9ac29dc 100644 --- a/scwx-qt/source/scwx/qt/types/text_event_key.cpp +++ b/scwx-qt/source/scwx/qt/types/text_event_key.cpp @@ -13,9 +13,18 @@ namespace types static const std::string logPrefix_ = "scwx::qt::types::text_event_key"; +std::string TextEventKey::ToFullString() const +{ + return std::format("{} {} {} {:04}", + officeId_, + awips::GetPhenomenonText(phenomenon_), + awips::GetSignificanceText(significance_), + etn_); +} + std::string TextEventKey::ToString() const { - return std::format("{}.{}.{}.{}", + return std::format("{}.{}.{}.{:04}", officeId_, awips::GetPhenomenonCode(phenomenon_), awips::GetSignificanceCode(significance_), diff --git a/scwx-qt/source/scwx/qt/types/text_event_key.hpp b/scwx-qt/source/scwx/qt/types/text_event_key.hpp index 8fd187eb..f962bcdf 100644 --- a/scwx-qt/source/scwx/qt/types/text_event_key.hpp +++ b/scwx-qt/source/scwx/qt/types/text_event_key.hpp @@ -20,6 +20,7 @@ struct TextEventKey { } + std::string ToFullString() const; std::string ToString() const; bool operator==(const TextEventKey& o) const; diff --git a/wxdata/include/scwx/awips/text_product_message.hpp b/wxdata/include/scwx/awips/text_product_message.hpp index 358a79ea..ec90f82d 100644 --- a/wxdata/include/scwx/awips/text_product_message.hpp +++ b/wxdata/include/scwx/awips/text_product_message.hpp @@ -87,6 +87,7 @@ public: TextProductMessage(TextProductMessage&&) noexcept; TextProductMessage& operator=(TextProductMessage&&) noexcept; + std::string message_content() const; std::shared_ptr wmo_header() const; std::vector mnd_header() const; std::vector overview_block() const; diff --git a/wxdata/include/scwx/common/characters.hpp b/wxdata/include/scwx/common/characters.hpp index f958d2fd..4da5f843 100644 --- a/wxdata/include/scwx/common/characters.hpp +++ b/wxdata/include/scwx/common/characters.hpp @@ -12,6 +12,8 @@ namespace Characters constexpr char DEGREE = static_cast(0xb0); constexpr char ETX = static_cast(0x03); +constexpr char NUL = static_cast(0x00); +constexpr char SOH = static_cast(0x01); } // namespace Characters diff --git a/wxdata/source/scwx/awips/text_product_message.cpp b/wxdata/source/scwx/awips/text_product_message.cpp index ce22f534..f03d3bce 100644 --- a/wxdata/source/scwx/awips/text_product_message.cpp +++ b/wxdata/source/scwx/awips/text_product_message.cpp @@ -6,6 +6,9 @@ #include #include +#include +#include + namespace scwx { namespace awips @@ -34,9 +37,17 @@ static std::optional TryParseVtecString(std::istream& is); class TextProductMessageImpl { public: - explicit TextProductMessageImpl() : wmoHeader_ {} {} + explicit TextProductMessageImpl() : + messageContent_ {}, + wmoHeader_ {}, + mndHeader_ {}, + overviewBlock_ {}, + segments_ {} + { + } ~TextProductMessageImpl() = default; + std::string messageContent_; std::shared_ptr wmoHeader_; std::vector mndHeader_; std::vector overviewBlock_; @@ -53,6 +64,11 @@ TextProductMessage::TextProductMessage(TextProductMessage&&) noexcept = default; TextProductMessage& TextProductMessage::operator=(TextProductMessage&&) noexcept = default; +std::string TextProductMessage::message_content() const +{ + return p->messageContent_; +} + std::shared_ptr TextProductMessage::wmo_header() const { return p->wmoHeader_; @@ -94,6 +110,8 @@ bool TextProductMessage::Parse(std::istream& is) { bool dataValid = true; + std::streampos messageStart = is.tellg(); + p->wmoHeader_ = std::make_shared(); dataValid = p->wmoHeader_->Parse(is); @@ -143,6 +161,37 @@ bool TextProductMessage::Parse(std::istream& is) } } + if (dataValid) + { + // Store raw message content + std::streampos messageEnd = is.tellg(); + std::streamsize messageSize = messageEnd - messageStart; + p->messageContent_.resize(messageEnd - messageStart); + is.seekg(messageStart); + if (is.peek() == common::Characters::SOH) + { + is.seekg(std::streamoff {1}, std::ios_base::cur); + messageSize--; + } + is.read(p->messageContent_.data(), messageSize); + + // Trim extra characters from raw message + while (p->messageContent_.size() > 0 && + (p->messageContent_.back() == common::Characters::NUL || + p->messageContent_.back() == common::Characters::ETX)) + { + p->messageContent_.resize(p->messageContent_.size() - 1); + } + boost::replace_all(p->messageContent_, "\r\r\n", "\n"); + boost::trim(p->messageContent_); + p->messageContent_.shrink_to_fit(); + } + else + { + p->messageContent_.resize(0); + p->messageContent_.shrink_to_fit(); + } + return dataValid; }