This commit is contained in:
@@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
namespace sp {
|
namespace sp {
|
||||||
|
|
||||||
bool IsSystemBigEndian();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Serialize value to (network byte order) big endian
|
* \brief Serialize value to (network byte order) big endian
|
||||||
*/
|
*/
|
||||||
@@ -36,19 +34,4 @@ void FromNetwork<std::uint32_t>(std::uint32_t& value);
|
|||||||
template <>
|
template <>
|
||||||
void FromNetwork<std::uint64_t>(std::uint64_t& value);
|
void FromNetwork<std::uint64_t>(std::uint64_t& value);
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Swap bytes if the value is any kind of integer
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
void TrySwapBytes(T& value) {}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
void TrySwapBytes<std::uint16_t>(std::uint16_t& value);
|
|
||||||
|
|
||||||
template <>
|
|
||||||
void TrySwapBytes<std::uint32_t>(std::uint32_t& value);
|
|
||||||
|
|
||||||
template <>
|
|
||||||
void TrySwapBytes<std::uint64_t>(std::uint64_t& value);
|
|
||||||
|
|
||||||
} // namespace sp
|
} // namespace sp
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <sp/protocol/GenericHandler.h>
|
|
||||||
#include <sp/protocol/Message.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace sp {
|
|
||||||
class PacketHandler;
|
|
||||||
|
|
||||||
using PacketID = std::uint8_t;
|
|
||||||
|
|
||||||
using PacketMessage = Message<
|
|
||||||
option::MsgIdType<PacketID>, // add id() operation
|
|
||||||
option::Handler<PacketHandler> // add dispatch() operation
|
|
||||||
>;
|
|
||||||
|
|
||||||
#define PacketConstructor(packetName) \
|
|
||||||
packetName##Packet() {} \
|
|
||||||
template <typename... Args> \
|
|
||||||
packetName##Packet(Args... args) { \
|
|
||||||
Construct(args...); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DeclarePacket(packetName) \
|
|
||||||
class packetName##Packet : public sp::MessageBase<sp::PacketMessage, \
|
|
||||||
sp::option::DispatchImpl<packetName##Packet>, sp::option::FieldsImpl<packetName##Fields>>, \
|
|
||||||
sp::option::ToStringImpl<packetName##Packet>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace sp
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <sp/default/DefaultPacket.h>
|
|
||||||
#include <sp/default/DefaultPacketHandler.h>
|
|
||||||
#include <sp/protocol/MessageDispatcher.h>
|
|
||||||
|
|
||||||
namespace sp {
|
|
||||||
|
|
||||||
using PacketDispatcher = MessageDispatcher<
|
|
||||||
PacketMessage::ParsedOptions::MsgIdType,
|
|
||||||
PacketMessage,
|
|
||||||
PacketMessage::ParsedOptions::HandlerType::HandlerT
|
|
||||||
>;
|
|
||||||
|
|
||||||
} // namespace sp
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <sp/protocol/MessageFactory.h>
|
|
||||||
|
|
||||||
namespace sp {
|
|
||||||
using PacketFactory = sp::MessageFactory<sp::PacketMessage, AllPackets>;
|
|
||||||
} // namespace sp
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <sp/protocol/GenericHandler.h>
|
|
||||||
|
|
||||||
// the tuple AllPackets must be defined !
|
|
||||||
|
|
||||||
namespace sp {
|
|
||||||
class PacketHandler : public sp::GenericHandler<PacketMessage, AllPackets> {};
|
|
||||||
} // namespace sp
|
|
||||||
@@ -14,7 +14,7 @@ class ConcreteMessage : public MessageBase<TMessageID, THandler> {
|
|||||||
|
|
||||||
virtual ~ConcreteMessage() {}
|
virtual ~ConcreteMessage() {}
|
||||||
|
|
||||||
virtual constexpr TMessageID GetId() const override {
|
virtual TMessageID GetId() const override {
|
||||||
return ID;
|
return ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <ostream>
|
|
||||||
#include <sp/protocol/Field.h>
|
|
||||||
#include <sp/protocol/message/OstreamFieldIterator.h>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace sp {
|
|
||||||
|
|
||||||
template <typename T, std::enable_if_t<details::is_primitive<T>::value, bool> = true>
|
|
||||||
std::ostream& operator<<(std::ostream& a_Stream, const PrintableField<T>& a_Field) {
|
|
||||||
return a_Stream << std::to_string(a_Field.GetValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& a_Stream, const PrintableField<long unsigned int>& a_Field) {
|
|
||||||
return a_Stream << a_Field.GetValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& a_Stream, const PrintableField<std::string>& a_Field) {
|
|
||||||
return a_Stream << "\"" << a_Field.GetValue() << "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename K, typename V>
|
|
||||||
std::ostream& operator<<(std::ostream& a_Stream, const PrintableField<std::pair<K, V>>& a_Data);
|
|
||||||
|
|
||||||
template <typename K, typename V>
|
|
||||||
std::ostream& operator<<(std::ostream& a_Stream, const PrintableField<std::map<K, V>>& a_Data);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::ostream& operator<<(std::ostream& a_Stream, const PrintableField<std::vector<T>>& a_Data);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename K, typename V>
|
|
||||||
std::ostream& operator<<(std::ostream& a_Stream, const PrintableField<std::pair<K, V>>& a_Data) {
|
|
||||||
return a_Stream << PrintableField<K>(a_Data.GetValue().first) << " => " << PrintableField<V>(a_Data.GetValue().second);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename K, typename V>
|
|
||||||
std::ostream& operator<<(std::ostream& a_Stream, const PrintableField<std::map<K, V>>& a_Data) {
|
|
||||||
a_Stream << "{";
|
|
||||||
std::copy(a_Data.GetValue().begin(), a_Data.GetValue().end(), OstreamFieldIterator<std::pair<K, V>>(std::cout, ", "));
|
|
||||||
return a_Stream << "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::ostream& operator<<(std::ostream& a_Stream, const PrintableField<std::vector<T>>& a_Data) {
|
|
||||||
a_Stream << "{";
|
|
||||||
std::copy(a_Data.GetValue().begin(), a_Data.GetValue().end(), OstreamFieldIterator<T>(std::cout, ", "));
|
|
||||||
return a_Stream << "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sp
|
|
||||||
@@ -1,27 +1,21 @@
|
|||||||
#include <sp/common/ByteSwapping.h>
|
#include <sp/common/ByteSwapping.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <endian.h>
|
||||||
|
|
||||||
|
#define htonll htobe64
|
||||||
|
#define ntohll be64toh
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace sp {
|
namespace sp {
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void SwapBytes(T& value) {
|
|
||||||
char* ptr = reinterpret_cast<char*>(&value);
|
|
||||||
std::reverse(ptr, ptr + sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsSystemBigEndian() {
|
|
||||||
static constexpr std::uint16_t test = 10;
|
|
||||||
static const bool isBigEndian = reinterpret_cast<const std::uint8_t*>(&test)[1] == 10;
|
|
||||||
return isBigEndian;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void ToNetwork<std::uint16_t>(std::uint16_t& value) {
|
void ToNetwork<std::uint16_t>(std::uint16_t& value) {
|
||||||
value = htons(value);
|
value = htons(value);
|
||||||
@@ -34,9 +28,7 @@ void ToNetwork<std::uint32_t>(std::uint32_t& value) {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
void ToNetwork<std::uint64_t>(std::uint64_t& value) {
|
void ToNetwork<std::uint64_t>(std::uint64_t& value) {
|
||||||
if (IsSystemBigEndian())
|
value = htonll(value);
|
||||||
return;
|
|
||||||
SwapBytes(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@@ -51,24 +43,7 @@ void FromNetwork<std::uint32_t>(std::uint32_t& value) {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
void FromNetwork<std::uint64_t>(std::uint64_t& value) {
|
void FromNetwork<std::uint64_t>(std::uint64_t& value) {
|
||||||
if (IsSystemBigEndian())
|
value = ntohll(value);
|
||||||
return;
|
|
||||||
SwapBytes(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
void TrySwapBytes<std::uint16_t>(std::uint16_t& value) {
|
|
||||||
SwapBytes(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
void TrySwapBytes<std::uint32_t>(std::uint32_t& value) {
|
|
||||||
SwapBytes(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
void TrySwapBytes<std::uint64_t>(std::uint64_t& value) {
|
|
||||||
SwapBytes(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sp
|
} // namespace sp
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ File::IOInterface(const std::string& a_FilePath, unsigned int a_OpenMode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
File::IOInterface(File&& other) :
|
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 File::Read(std::size_t a_Amount) {
|
||||||
DataBuffer buffer;
|
DataBuffer buffer;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ using PacketDispatcher = sp::MessageDispatcher<PacketBase>;
|
|||||||
using PacketFactory = sp::MessageFactory<PacketBase, AllMessages>;
|
using PacketFactory = sp::MessageFactory<PacketBase, AllMessages>;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
KeepAliveMessage m{5U};
|
KeepAliveMessage m{5UL};
|
||||||
MyHandler h;
|
MyHandler h;
|
||||||
PacketDispatcher d;
|
PacketDispatcher d;
|
||||||
d.RegisterHandler(PacketID::KeepAlive, &h);
|
d.RegisterHandler(PacketID::KeepAlive, &h);
|
||||||
|
|||||||
155
test/type_name.hpp
Normal file
155
test/type_name.hpp
Normal file
@@ -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 <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#if __has_include(<cxxabi.h>)
|
||||||
|
# include <cxxabi.h>
|
||||||
|
# include <cstdlib>
|
||||||
|
# include <memory>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
constexpr bool CXXABI
|
||||||
|
{
|
||||||
|
#if __has_include(<cxxabi.h>)
|
||||||
|
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<T>() for extracting a type's name.
|
||||||
|
(2) A variable template type_name_rt<T> initialized to the type's name.
|
||||||
|
(also an incomplete class template IdT<T>, 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<T>()
|
||||||
|
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<T>
|
||||||
|
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: <string>,<string_view>,<type_traits> for std::conditional
|
||||||
|
<typeinfo> (RTTI)
|
||||||
|
for typeid(T).name(), an implementation-defined name.
|
||||||
|
<cxxabi.h> (on CXXABI platforms only - GCC, Clang, etc.)
|
||||||
|
for abi::__cxa_demangle(name,...)
|
||||||
|
to map typeid(T).name to a human readable name for T.
|
||||||
|
<cstdlib> for std::free, <memory> for std::unique_ptr
|
||||||
|
E.g.
|
||||||
|
int i;
|
||||||
|
std::cout << type_name_rt<decltype(i)> << "\n^^^ tada!";
|
||||||
|
--- stdout ---
|
||||||
|
int
|
||||||
|
^^^ tada!
|
||||||
|
*/
|
||||||
|
|
||||||
|
// IdT<T> 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 <typename T> struct IdT {};
|
||||||
|
|
||||||
|
namespace impl
|
||||||
|
{
|
||||||
|
// demangle<bool Free=false>( 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<char> (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 <bool Free = false>
|
||||||
|
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<char, decltype(std::free)*>( dmg, std::free);
|
||||||
|
else
|
||||||
|
return dmg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// prefix_len (constant): prefix length of demangled typeid(IdT<T>)
|
||||||
|
// 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<int>).name()))
|
||||||
|
- std::strlen("int>");
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_cvref_v = !std::is_same_v<T,remove_cvref_t<T>>;
|
||||||
|
|
||||||
|
// type_name_rt<T>() Returns string, frees any malloc from ABI demangle
|
||||||
|
// type_name_rt<T,false>() Returns string_view, does not free demangle malloc
|
||||||
|
//
|
||||||
|
template <typename T, bool Free = true, typename = void>
|
||||||
|
auto
|
||||||
|
type_name_rt() noexcept(!CXXABI) -> std::conditional_t<Free, std::string,
|
||||||
|
std::string_view>
|
||||||
|
{
|
||||||
|
if constexpr (!is_cvref_v<T>)
|
||||||
|
{
|
||||||
|
if (auto dmg = demangle<Free>(typeid(T).name()))
|
||||||
|
{
|
||||||
|
return { &*dmg };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // wrap all cvref types for now - maybe only do functions and arrays
|
||||||
|
{
|
||||||
|
if (auto dmg = demangle<Free>(typeid(IdT<T>).name()))
|
||||||
|
{
|
||||||
|
size_t const p = IdT_prefix_len();
|
||||||
|
return { &*dmg + p, std::strlen(&*dmg) - p - 1 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
} // namespace impl
|
||||||
|
|
||||||
|
// type_name_str<T>() Returns a std::string copy of the demangled typeid name.
|
||||||
|
//
|
||||||
|
template <typename T>
|
||||||
|
std::string
|
||||||
|
const type_name_str() { return impl::type_name_rt<T>(); }
|
||||||
|
|
||||||
|
// type_name_rt<T> Global constant; "The Demangle that Never Dangles"
|
||||||
|
//
|
||||||
|
template <typename T>
|
||||||
|
inline
|
||||||
|
std::string_view
|
||||||
|
const type_name_rt = impl::type_name_rt<T, false>();
|
||||||
Reference in New Issue
Block a user