From 073872df944a4639124f3d40cf67a9743e54926d Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Thu, 26 Jun 2025 14:43:27 +0200 Subject: [PATCH] byte swapping --- include/sp/common/ByteSwapping.h | 17 -- include/sp/default/DefaultPacket.h | 31 ---- include/sp/default/DefaultPacketDispatcher.h | 15 -- include/sp/default/DefaultPacketFactory.h | 7 - include/sp/default/DefaultPacketHandler.h | 9 -- include/sp/protocol/ConcreteMessage.h | 2 +- include/sp/protocol/MessagePrinter.h | 61 -------- src/sp/common/ByteSwapping.cpp | 45 ++---- src/sp/io/File.cpp | 2 +- test/test_message.cpp | 2 +- test/type_name.hpp | 155 +++++++++++++++++++ 11 files changed, 168 insertions(+), 178 deletions(-) delete mode 100644 include/sp/default/DefaultPacket.h delete mode 100644 include/sp/default/DefaultPacketDispatcher.h delete mode 100644 include/sp/default/DefaultPacketFactory.h delete mode 100644 include/sp/default/DefaultPacketHandler.h delete mode 100644 include/sp/protocol/MessagePrinter.h create mode 100644 test/type_name.hpp diff --git a/include/sp/common/ByteSwapping.h b/include/sp/common/ByteSwapping.h index 907c215..19578a5 100644 --- a/include/sp/common/ByteSwapping.h +++ b/include/sp/common/ByteSwapping.h @@ -4,8 +4,6 @@ namespace sp { -bool IsSystemBigEndian(); - /** * \brief Serialize value to (network byte order) big endian */ @@ -36,19 +34,4 @@ void FromNetwork(std::uint32_t& value); template <> void FromNetwork(std::uint64_t& value); -/** - * \brief Swap bytes if the value is any kind of integer - */ -template -void TrySwapBytes(T& value) {} - -template <> -void TrySwapBytes(std::uint16_t& value); - -template <> -void TrySwapBytes(std::uint32_t& value); - -template <> -void TrySwapBytes(std::uint64_t& value); - } // namespace sp diff --git a/include/sp/default/DefaultPacket.h b/include/sp/default/DefaultPacket.h deleted file mode 100644 index 3882a40..0000000 --- a/include/sp/default/DefaultPacket.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include - - -namespace sp { -class PacketHandler; - -using PacketID = std::uint8_t; - -using PacketMessage = Message< - option::MsgIdType, // add id() operation - option::Handler // add dispatch() operation - >; - -#define PacketConstructor(packetName) \ - packetName##Packet() {} \ - template \ - packetName##Packet(Args... args) { \ - Construct(args...); \ - } - -#define DeclarePacket(packetName) \ - class packetName##Packet : public sp::MessageBase, sp::option::FieldsImpl>, \ - sp::option::ToStringImpl - - - -} // namespace sp diff --git a/include/sp/default/DefaultPacketDispatcher.h b/include/sp/default/DefaultPacketDispatcher.h deleted file mode 100644 index aeb7fd5..0000000 --- a/include/sp/default/DefaultPacketDispatcher.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace sp { - -using PacketDispatcher = MessageDispatcher< - PacketMessage::ParsedOptions::MsgIdType, - PacketMessage, - PacketMessage::ParsedOptions::HandlerType::HandlerT - >; - -} // namespace sp diff --git a/include/sp/default/DefaultPacketFactory.h b/include/sp/default/DefaultPacketFactory.h deleted file mode 100644 index 8f7e4bd..0000000 --- a/include/sp/default/DefaultPacketFactory.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -namespace sp { -using PacketFactory = sp::MessageFactory; -} // namespace sp diff --git a/include/sp/default/DefaultPacketHandler.h b/include/sp/default/DefaultPacketHandler.h deleted file mode 100644 index 6be435d..0000000 --- a/include/sp/default/DefaultPacketHandler.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include - -// the tuple AllPackets must be defined ! - -namespace sp { -class PacketHandler : public sp::GenericHandler {}; -} // namespace sp diff --git a/include/sp/protocol/ConcreteMessage.h b/include/sp/protocol/ConcreteMessage.h index b057276..78bc34a 100644 --- a/include/sp/protocol/ConcreteMessage.h +++ b/include/sp/protocol/ConcreteMessage.h @@ -14,7 +14,7 @@ class ConcreteMessage : public MessageBase { virtual ~ConcreteMessage() {} - virtual constexpr TMessageID GetId() const override { + virtual TMessageID GetId() const override { return ID; } diff --git a/include/sp/protocol/MessagePrinter.h b/include/sp/protocol/MessagePrinter.h deleted file mode 100644 index 7c3b8c7..0000000 --- a/include/sp/protocol/MessagePrinter.h +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace sp { - -template ::value, bool> = true> -std::ostream& operator<<(std::ostream& a_Stream, const PrintableField& a_Field) { - return a_Stream << std::to_string(a_Field.GetValue()); -} - -inline std::ostream& operator<<(std::ostream& a_Stream, const PrintableField& a_Field) { - return a_Stream << a_Field.GetValue(); -} - -inline std::ostream& operator<<(std::ostream& a_Stream, const PrintableField& a_Field) { - return a_Stream << "\"" << a_Field.GetValue() << "\""; -} - - - - - -template -std::ostream& operator<<(std::ostream& a_Stream, const PrintableField>& a_Data); - -template -std::ostream& operator<<(std::ostream& a_Stream, const PrintableField>& a_Data); - -template -std::ostream& operator<<(std::ostream& a_Stream, const PrintableField>& a_Data); - - - - - -template -std::ostream& operator<<(std::ostream& a_Stream, const PrintableField>& a_Data) { - return a_Stream << PrintableField(a_Data.GetValue().first) << " => " << PrintableField(a_Data.GetValue().second); -} - -template -std::ostream& operator<<(std::ostream& a_Stream, const PrintableField>& a_Data) { - a_Stream << "{"; - std::copy(a_Data.GetValue().begin(), a_Data.GetValue().end(), OstreamFieldIterator>(std::cout, ", ")); - return a_Stream << "}"; -} - -template -std::ostream& operator<<(std::ostream& a_Stream, const PrintableField>& a_Data) { - a_Stream << "{"; - std::copy(a_Data.GetValue().begin(), a_Data.GetValue().end(), OstreamFieldIterator(std::cout, ", ")); - return a_Stream << "}"; -} - -} // namespace sp diff --git a/src/sp/common/ByteSwapping.cpp b/src/sp/common/ByteSwapping.cpp index b6f15a2..3a02546 100644 --- a/src/sp/common/ByteSwapping.cpp +++ b/src/sp/common/ByteSwapping.cpp @@ -1,27 +1,21 @@ #include #ifdef _WIN32 + #include + #else + #include +#include + +#define htonll htobe64 +#define ntohll be64toh + #endif -#include - namespace sp { -template -void SwapBytes(T& value) { - char* ptr = reinterpret_cast(&value); - std::reverse(ptr, ptr + sizeof(T)); -} - -bool IsSystemBigEndian() { - static constexpr std::uint16_t test = 10; - static const bool isBigEndian = reinterpret_cast(&test)[1] == 10; - return isBigEndian; -} - template <> void ToNetwork(std::uint16_t& value) { value = htons(value); @@ -34,9 +28,7 @@ void ToNetwork(std::uint32_t& value) { template <> void ToNetwork(std::uint64_t& value) { - if (IsSystemBigEndian()) - return; - SwapBytes(value); + value = htonll(value); } template <> @@ -51,24 +43,7 @@ void FromNetwork(std::uint32_t& value) { template <> void FromNetwork(std::uint64_t& value) { - if (IsSystemBigEndian()) - return; - SwapBytes(value); -} - -template <> -void TrySwapBytes(std::uint16_t& value) { - SwapBytes(value); -} - -template <> -void TrySwapBytes(std::uint32_t& value) { - SwapBytes(value); -} - -template <> -void TrySwapBytes(std::uint64_t& value) { - SwapBytes(value); + value = ntohll(value); } } // namespace sp diff --git a/src/sp/io/File.cpp b/src/sp/io/File.cpp index 2bccc19..300c0aa 100644 --- a/src/sp/io/File.cpp +++ b/src/sp/io/File.cpp @@ -11,7 +11,7 @@ File::IOInterface(const std::string& a_FilePath, unsigned int a_OpenMode) { } File::IOInterface(File&& other) : - m_FileOutput(std::move(other.m_FileOutput)), m_FileInput(std::move(other.m_FileInput)) {} + m_FileInput(std::move(other.m_FileInput)), m_FileOutput(std::move(other.m_FileOutput)) {} DataBuffer File::Read(std::size_t a_Amount) { DataBuffer buffer; diff --git a/test/test_message.cpp b/test/test_message.cpp index 047ab2a..f135d7b 100644 --- a/test/test_message.cpp +++ b/test/test_message.cpp @@ -37,7 +37,7 @@ using PacketDispatcher = sp::MessageDispatcher; using PacketFactory = sp::MessageFactory; int main() { - KeepAliveMessage m{5U}; + KeepAliveMessage m{5UL}; MyHandler h; PacketDispatcher d; d.RegisterHandler(PacketID::KeepAlive, &h); diff --git a/test/type_name.hpp b/test/type_name.hpp new file mode 100644 index 0000000..f8afd63 --- /dev/null +++ b/test/type_name.hpp @@ -0,0 +1,155 @@ +// Copyright (c) 2018 Will Wray https://keybase.io/willwray +// +// Distributed under the Boost Software License, Version 1.0. +// (http://www.boost.org/LICENSE_1_0.txt) + +#pragma once + +#include +#include +#include +#include +#include + +#if __has_include() +# include +# include +# include +#endif + +constexpr bool CXXABI +{ +#if __has_include() + true +#endif +}; + +/* + "type_name_rt.hpp": get type names at runtime (hence 'rt') + ^^^^^^^^^^^^^^^^ + This header defines, in global scope (i.e. not namespace'd): + (1) A function template type_name_str() for extracting a type's name. + (2) A variable template type_name_rt initialized to the type's name. + (also an incomplete class template IdT, an implementation detail.) + The template type parameter T is mapped to a readable name for the type. + The work is done at runtime by what is the most standard current method; + runtime type information (RTTI) and, on CXXABI, a demangle call + (for compile-time alternatives see type_name_pt or type_name_ct). + (1) type_name_str() + Returns a std::string copy of the demangled typeid name. + On each call it does all the work, and cleans it all up + (i.e. it frees any demangle allocation once copied from). + + (2) type_name_rt + A std::string_view global constant (a view into the + demangle buffer, on CXXABI, which is not ever free'd). + All work is done in static initialization, before main() + + Failure is signalled by an empty return value; "" + (indicates a demangle failure as typeid is assumed fail-safe). + Requirements: + C++17 for string_view, constexpr-if, CTAD (unique_ptr) and __has_include + RTTI, the compiler's runtime type information, must be enabled + Dependencies: ,, for std::conditional + (RTTI) + for typeid(T).name(), an implementation-defined name. + (on CXXABI platforms only - GCC, Clang, etc.) + for abi::__cxa_demangle(name,...) + to map typeid(T).name to a human readable name for T. + for std::free, for std::unique_ptr + E.g. + int i; + std::cout << type_name_rt << "\n^^^ tada!"; + --- stdout --- + int + ^^^ tada! +*/ + +// IdT wraps T as template param so typeid can't decay ref or cv quals. +// An implementation detail; must be a 3-character id, any 3 chars will do. +template struct IdT {}; + +namespace impl +{ +// demangle( const char* name) +// +// (1) On non-CXXABI returns name, regardless of the template parameter. +// i.e. the function does nothing but return its parameter, a char*. +// +// (2) On CXXABI the demangle ABI is called and the result is returned +// with return type depending on the boolean template argument: +// (a) char* by default (Free=false). Any demangle malloc is not free'd. +// (b) unique_ptr (Free=true) to RAII-free any malloc'd chars. +// +// The input name should be a valid mangled name like typeid(T).name() +// Null return value implies demangle fail (no malloc, free is harmless). +// +template +auto +demangle(char const* name) noexcept(!CXXABI) +{ + if constexpr (!CXXABI) { + return name; // NOP: assume already demangled if not on CXXABI + } else { + auto dmg = abi::__cxa_demangle(name, nullptr, nullptr, nullptr); + if constexpr (Free) + return std::unique_ptr( dmg, std::free); + else + return dmg; + } +} + +// prefix_len (constant): prefix length of demangled typeid(IdT) +// for different compilers (remove 4 chars "int>" from the length) +size_t IdT_prefix_len() +{ + static size_t const len = std::strlen(demangle<>(typeid(IdT).name())) + - std::strlen("int>"); + return len; +} + +template +using remove_cvref_t = std::remove_cv_t>; + +template +inline constexpr bool is_cvref_v = !std::is_same_v>; + +// type_name_rt() Returns string, frees any malloc from ABI demangle +// type_name_rt() Returns string_view, does not free demangle malloc +// +template +auto +type_name_rt() noexcept(!CXXABI) -> std::conditional_t +{ + if constexpr (!is_cvref_v) + { + if (auto dmg = demangle(typeid(T).name())) + { + return { &*dmg }; + } + } + else // wrap all cvref types for now - maybe only do functions and arrays + { + if (auto dmg = demangle(typeid(IdT).name())) + { + size_t const p = IdT_prefix_len(); + return { &*dmg + p, std::strlen(&*dmg) - p - 1 }; + } + } + return ""; +} +} // namespace impl + +// type_name_str() Returns a std::string copy of the demangled typeid name. +// +template +std::string +const type_name_str() { return impl::type_name_rt(); } + +// type_name_rt Global constant; "The Demangle that Never Dangles" +// +template +inline +std::string_view +const type_name_rt = impl::type_name_rt(); \ No newline at end of file