#pragma once #include #include #include #include #include #include #ifdef WIN32 # include #else # include #endif namespace scwx { namespace wsr88d { namespace rda { class MessageImpl; class Message { protected: explicit Message(); Message(const Message&) = delete; Message& operator=(const Message&) = delete; Message(Message&&) noexcept; Message& operator=(Message&&) noexcept; bool ValidateMessage(std::istream& is, size_t bytesRead) const; static void ReadBoolean(std::istream& is, bool& value) { std::string data(4, ' '); is.read(reinterpret_cast(&data[0]), 4); value = (data.at(0) == 'T'); } static void ReadChar(std::istream& is, char& value) { std::string data(4, ' '); is.read(reinterpret_cast(&data[0]), 4); value = data.at(0); } static float SwapFloat(float f) { return ntohf(*reinterpret_cast(&f)); } template static void SwapFloatArray(std::array& arr) { std::transform(std::execution::par_unseq, arr.begin(), arr.end(), arr.begin(), [](float f) { return SwapFloat(f); }); } template static void SwapUInt16Array(std::array& arr) { std::transform(std::execution::par_unseq, arr.begin(), arr.end(), arr.begin(), [](uint16_t u) { return ntohs(u); }); } template static void SwapFloatMap(std::map& m) { std::for_each(std::execution::par_unseq, m.begin(), m.end(), [](auto& p) { p.second = SwapFloat(p.second); }); } public: virtual ~Message(); const MessageHeader& header() const; void set_header(MessageHeader&& header); virtual bool Parse(std::istream& is) = 0; private: std::unique_ptr p; }; } // namespace rda } // namespace wsr88d } // namespace scwx