#pragma once #include #include #include #include #include #include #ifdef _WIN32 # include #else # include #endif namespace scwx::awips { class Message { protected: explicit Message(); Message(const Message&) = delete; Message& operator=(const Message&) = delete; Message(Message&&) noexcept; Message& operator=(Message&&) noexcept; virtual bool ValidateMessage(std::istream& is, std::size_t bytesRead) const; public: virtual ~Message(); virtual std::size_t data_size() const = 0; virtual bool Parse(std::istream& is) = 0; 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) { std::uint32_t temp; std::memcpy(&temp, &f, sizeof(std::uint32_t)); temp = ntohl(temp); std::memcpy(&f, &temp, sizeof(float)); return f; } static double SwapDouble(double d) { std::uint64_t temp; std::memcpy(&temp, &d, sizeof(std::uint64_t)); temp = ntohll(temp); std::memcpy(&d, &temp, sizeof(float)); return d; } template static void SwapArray(std::array& arr, std::size_t size = _Size) { std::transform(std::execution::par_unseq, arr.begin(), arr.begin() + size, arr.begin(), [](float f) { return SwapFloat(f); }); } template static void SwapArray(std::array& arr, std::size_t size = _Size) { std::transform(std::execution::par_unseq, arr.begin(), arr.begin() + size, arr.begin(), [](std::int16_t u) { return ntohs(u); }); } template static void SwapArray(std::array& arr, std::size_t size = _Size) { std::transform(std::execution::par_unseq, arr.begin(), arr.begin() + size, arr.begin(), [](std::uint16_t u) { return ntohs(u); }); } template static void SwapArray(std::array& arr, std::size_t size = _Size) { std::transform(std::execution::par_unseq, arr.begin(), arr.begin() + size, arr.begin(), [](std::uint32_t u) { return ntohl(u); }); } template static void SwapMap(std::map& m) { std::for_each(std::execution::par_unseq, m.begin(), m.end(), [](auto& p) { p.second = SwapFloat(p.second); }); } template static void SwapVector(std::vector& v) { std::transform(std::execution::par_unseq, v.begin(), v.end(), v.begin(), [](T u) { if constexpr (std::is_same_v || std::is_same_v) { return static_cast(ntohs(u)); } else if constexpr (std::is_same_v || std::is_same_v) { return static_cast(ntohl(u)); } else if constexpr (std::is_same_v || std::is_same_v) { return static_cast(ntohll(u)); } else if constexpr (std::is_same_v) { return SwapFloat(u); } else if constexpr (std::is_same_v) { return SwapDouble(u); } else { static_assert(std::is_same_v, "Unsupported type for SwapVector"); } }); } private: class Impl; std::unique_ptr p; }; } // namespace scwx::awips