Loading src/GTMesh/BinarySerializer/BinarySerializer.h 0 → 100644 +121 −0 Original line number Diff line number Diff line #ifndef BINARYSERIALIZER_H #define BINARYSERIALIZER_H #include <vector> #include <cstdint> // TODO možná změnit jméno /** * @brief The BinarySerializer class holds binary array and is able to * store binary data as well as serialize and deserialize data */ class BinarySerializer { public: using Byte = uint8_t; using ByteContainer = std::vector<Byte>; using ByteContainerIterator = ByteContainer::const_iterator; template<typename T> static void addNext(std::vector<Byte>& binaryDataContainer, const T& data); template <typename T> static void readNext(std::vector<Byte>::const_iterator& binaryDataIterator, T& data); template <typename T> static T readNext(std::vector<Byte>::const_iterator& binaryDataIterator) { T data; readNext(binaryDataIterator, data); return data; } template<typename T> void maddNext(const T& data) { addNext(mData, data); } template <typename T> void mreadNext(T& data) { readNext(mDataIterator, data); } template <typename T> T mreadNext() { return readNext<T>(mDataIterator); } void resetIterator() { mDataIterator = mData.cbegin(); } //private: ByteContainer mData; ByteContainerIterator mDataIterator; }; #include "Serializers/SerializeCustom.h" #include "Serializers/SerializeSimple.h" #include "Serializers/SerializeIterable.h" #include "Serializers/SerializeTuple.h" #include <GTMesh/Utils/ClassSelector.h> namespace Impl { template<typename VarType, typename Serializer, typename = void> struct IsSerializableBy : public std::false_type {}; template<typename VarType, typename Serializer> struct IsSerializableBy<VarType, Serializer, decltype(Serializer::serialize(std::declval<std::vector<unsigned char> &>(), std::declval<const VarType &>()))> : public std::true_type {}; template<typename VarType, typename Serializer, typename = void> struct IsDeserializableBy : public std::false_type {}; template<typename VarType, typename Serializer> struct IsDeserializableBy< VarType, Serializer, decltype(Serializer::deserialize(std::declval<std::vector<unsigned char>::const_iterator &>(), std::declval<const VarType &>()))> : public std::true_type {}; } // Impl namespace template<typename VarType, typename Serializer> struct IsSerializableBy: public Impl::IsSerializableBy<VarType, Serializer> {}; template<typename VarType, typename... Serializers> using SelectSerializer = ClassSelector<VarType, IsSerializableBy, Serializers...>; template<typename T> void BinarySerializer::addNext(std::vector<BinarySerializer::Byte> &binaryDataContainer, const T &data) { SelectSerializer<T, SerializeCustom, SerializeSimple, SerializeIterable, SerializeTuple>:: SelectedClass::serialize(binaryDataContainer, data); } template<typename VarType, typename Serializer> struct IsDeserializableBy: public Impl::IsDeserializableBy<VarType, Serializer> {}; template<typename VarType, typename... Serializers> using SelectDeserializer = ClassSelector<VarType, IsDeserializableBy, Serializers...>; template<typename T> void BinarySerializer::readNext(std::vector<Byte>::const_iterator& binaryDataIterator, T& data) { SelectDeserializer<T, SerializeCustom, SerializeSimple, DeserializeAsociativeMap, DeserializeAsociativeSet, SerializeIterable, SerializeTuple>::SelectedClass::deserialize(binaryDataIterator, data); } #endif // BINARYSERIALIZER_H src/GTMesh/BinarySerializer/Serializers/SerializeCustom.h 0 → 100644 +30 −0 Original line number Diff line number Diff line #ifndef SERIALIZECUSTOM_H #define SERIALIZECUSTOM_H #include "../BinarySerializer.h" #include <GTMesh/Traits/CustomTypeTraits.h> struct SerializeCustom { template <typename T> using IsBitviseSerializable = Impl::void_t<decltype(BinarySerialize(std::declval<BinarySerializer::ByteContainer&>(), std::declval<const T&>()))>; template <typename T> using IsBitviseDeserializable = Impl::void_t<decltype(BinaryDeserialize(std::declval<BinarySerializer::ByteContainerIterator&>(), std::declval<const T&>()))>; template <typename T> static IsBitviseSerializable<T> serialize(BinarySerializer::ByteContainer& dataContainer, const T& data, ...) { BinarySerialize(dataContainer, data); } template <typename T> static IsBitviseDeserializable<T> deserialize(BinarySerializer::ByteContainerIterator& dataIterator, T& data, ...) { BinaryDeserialize(dataIterator, data); } }; #endif // SERIALIZECUSTOM_H src/GTMesh/BinarySerializer/Serializers/SerializeIterable.h 0 → 100644 +64 −0 Original line number Diff line number Diff line #ifndef SERIALIZEITERABLE_H #define SERIALIZEITERABLE_H #include <GTMesh/Traits/CustomTypeTraits.h> #include "../BinarySerializer.h" struct SerializeIterable { template <typename T, typename ..., std::enable_if_t<IsIterable<T>::value, bool> = true> static void serialize(std::vector<unsigned char>& dataContainer, const T& data){ BinarySerializer::addNext(dataContainer, data.size()); for (const auto& val : data) { BinarySerializer::addNext(dataContainer, val); } } template <typename T, typename ..., std::enable_if_t<IsIterable<T>::value, bool> = true> static void deserialize(std::vector<unsigned char>::const_iterator& dataIterator, T& data){ decltype(data.size()) size = BinarySerializer::readNext<decltype(data.size())>(dataIterator); if (data.size() != size) { data.resize(size); } for (auto & val : data) { BinarySerializer::readNext(dataIterator, val); } } // TODO think how to deserialize lists and maps }; struct DeserializeAsociativeMap { template <typename T, typename ..., std::enable_if_t<IsIterable<T>::value, bool> = true> static Impl::void_t<typename T::key_type,typename T::mapped_type> deserialize(std::vector<unsigned char>::const_iterator& dataIterator, T& data){ decltype(data.size()) size = BinarySerializer::readNext<decltype(data.size())>(dataIterator); for (decltype(data.size()) i = 0; i < size; i ++) { std::pair<typename T::key_type,typename T::mapped_type> val; BinarySerializer::readNext(dataIterator, val); data.insert(val); } } }; struct DeserializeAsociativeSet { template <typename T, typename ..., std::enable_if_t<IsIterable<T>::value, bool> = true> static Impl::void_t<typename T::key_type> deserialize(std::vector<unsigned char>::const_iterator& dataIterator, T& data){ decltype(data.size()) size = BinarySerializer::readNext<decltype(data.size())>(dataIterator); for (decltype(data.size()) i = 0; i < size; i ++) { typename T::key_type val; BinarySerializer::readNext(dataIterator, val); data.insert(val); } } }; #endif // SERIALIZEITERABLE_H src/GTMesh/BinarySerializer/Serializers/SerializeSimple.h 0 → 100644 +50 −0 Original line number Diff line number Diff line #ifndef SERIALIZESIMPLE_H #define SERIALIZESIMPLE_H #include <type_traits> #include <vector> #include <stdexcept> namespace Impl { template<typename T> inline constexpr bool IsSimpleSerializable_v = !std::is_class<T>::value; } /** * @brief The SerializeSimple struct serializes simple types as double or int. */ struct SerializeSimple { template <typename T, typename ..., std::enable_if_t<Impl::IsSimpleSerializable_v<T>, bool> = true> static void serialize(std::vector<unsigned char>& dataContainer, const T& data){ const unsigned char* pData = reinterpret_cast<const unsigned char*>(&data); dataContainer.insert(dataContainer.end(), pData, pData + sizeof (T)); } template <typename T, typename ..., std::enable_if_t<Impl::IsSimpleSerializable_v<T>, bool> = true> static void deserialize(std::vector<unsigned char>::const_iterator& dataIterator, T& data){ unsigned char *const pData = reinterpret_cast<unsigned char*>(&data); for (size_t i = 0; i < sizeof (T); i++) { pData[i] = *dataIterator; dataIterator++; } } static void serialize(std::vector<unsigned char>& dataContainer, const bool data){ dataContainer.push_back(data ? 1 : 0); } template <typename T, typename ..., std::enable_if_t<Impl::IsSimpleSerializable_v<T>, bool> = true> static void deserialize(std::vector<unsigned char>::const_iterator& dataIterator, bool& data){ switch (*dataIterator) { case 1: data = true; break; case 0: data = false; break; default: throw std::runtime_error(std::to_string((int)*dataIterator & 0xff) + ": invalid data input for bool 1/0 expected"); } } }; #endif // SERIALIZESIMPLE_H src/GTMesh/BinarySerializer/Serializers/SerializeTuple.h 0 → 100644 +53 −0 Original line number Diff line number Diff line #ifndef SERIALIZETUPLE_H #define SERIALIZETUPLE_H #include "../BinarySerializer.h" #include <GTMesh/Utils/ConstexprFor.h> #include <tuple> struct SerializeTuple { /** * @brief Python-like print of dictionary pair of key and value. */ template<typename T1, typename T2> static void serialize(BinarySerializer::ByteContainer& dataContainer, const std::pair<T1,T2>& data, ...) { BinarySerializer::addNext(dataContainer, data.first); BinarySerializer::addNext(dataContainer, data.second); } template<typename T1, typename T2> static void deserialize(BinarySerializer::ByteContainerIterator& dataIterator, std::pair<T1,T2>& data, ...) { BinarySerializer::readNext(dataIterator, data.first); BinarySerializer::readNext(dataIterator, data.second); } struct SerializeTupleHelper{ template <unsigned int Index, typename ... TupleTypes> static void exec(BinarySerializer::ByteContainer& dataContainer, const std::tuple<TupleTypes...>& data) { BinarySerializer::addNext(dataContainer, std::get<Index>(data)); } }; template<typename ... TupleTypes> static void serialize(BinarySerializer::ByteContainer& dataContainer, const std::tuple<TupleTypes...>& data, ...) { constexprFor<SerializeTupleHelper, sizeof... (TupleTypes)>(dataContainer, data); } struct DeserializeTupleHelper{ template <unsigned int Index, typename ... TupleTypes> static void exec(BinarySerializer::ByteContainerIterator& dataIterator, std::tuple<TupleTypes...>& data) { BinarySerializer::readNext(dataIterator, std::get<Index>(data)); } }; template<typename ... TupleTypes> static void deserialize(BinarySerializer::ByteContainerIterator& dataIterator, std::tuple<TupleTypes...>& data, ...) { constexprFor<DeserializeTupleHelper, sizeof... (TupleTypes)>(dataIterator, data); } }; #endif // SERIALIZETUPLE_H Loading
src/GTMesh/BinarySerializer/BinarySerializer.h 0 → 100644 +121 −0 Original line number Diff line number Diff line #ifndef BINARYSERIALIZER_H #define BINARYSERIALIZER_H #include <vector> #include <cstdint> // TODO možná změnit jméno /** * @brief The BinarySerializer class holds binary array and is able to * store binary data as well as serialize and deserialize data */ class BinarySerializer { public: using Byte = uint8_t; using ByteContainer = std::vector<Byte>; using ByteContainerIterator = ByteContainer::const_iterator; template<typename T> static void addNext(std::vector<Byte>& binaryDataContainer, const T& data); template <typename T> static void readNext(std::vector<Byte>::const_iterator& binaryDataIterator, T& data); template <typename T> static T readNext(std::vector<Byte>::const_iterator& binaryDataIterator) { T data; readNext(binaryDataIterator, data); return data; } template<typename T> void maddNext(const T& data) { addNext(mData, data); } template <typename T> void mreadNext(T& data) { readNext(mDataIterator, data); } template <typename T> T mreadNext() { return readNext<T>(mDataIterator); } void resetIterator() { mDataIterator = mData.cbegin(); } //private: ByteContainer mData; ByteContainerIterator mDataIterator; }; #include "Serializers/SerializeCustom.h" #include "Serializers/SerializeSimple.h" #include "Serializers/SerializeIterable.h" #include "Serializers/SerializeTuple.h" #include <GTMesh/Utils/ClassSelector.h> namespace Impl { template<typename VarType, typename Serializer, typename = void> struct IsSerializableBy : public std::false_type {}; template<typename VarType, typename Serializer> struct IsSerializableBy<VarType, Serializer, decltype(Serializer::serialize(std::declval<std::vector<unsigned char> &>(), std::declval<const VarType &>()))> : public std::true_type {}; template<typename VarType, typename Serializer, typename = void> struct IsDeserializableBy : public std::false_type {}; template<typename VarType, typename Serializer> struct IsDeserializableBy< VarType, Serializer, decltype(Serializer::deserialize(std::declval<std::vector<unsigned char>::const_iterator &>(), std::declval<const VarType &>()))> : public std::true_type {}; } // Impl namespace template<typename VarType, typename Serializer> struct IsSerializableBy: public Impl::IsSerializableBy<VarType, Serializer> {}; template<typename VarType, typename... Serializers> using SelectSerializer = ClassSelector<VarType, IsSerializableBy, Serializers...>; template<typename T> void BinarySerializer::addNext(std::vector<BinarySerializer::Byte> &binaryDataContainer, const T &data) { SelectSerializer<T, SerializeCustom, SerializeSimple, SerializeIterable, SerializeTuple>:: SelectedClass::serialize(binaryDataContainer, data); } template<typename VarType, typename Serializer> struct IsDeserializableBy: public Impl::IsDeserializableBy<VarType, Serializer> {}; template<typename VarType, typename... Serializers> using SelectDeserializer = ClassSelector<VarType, IsDeserializableBy, Serializers...>; template<typename T> void BinarySerializer::readNext(std::vector<Byte>::const_iterator& binaryDataIterator, T& data) { SelectDeserializer<T, SerializeCustom, SerializeSimple, DeserializeAsociativeMap, DeserializeAsociativeSet, SerializeIterable, SerializeTuple>::SelectedClass::deserialize(binaryDataIterator, data); } #endif // BINARYSERIALIZER_H
src/GTMesh/BinarySerializer/Serializers/SerializeCustom.h 0 → 100644 +30 −0 Original line number Diff line number Diff line #ifndef SERIALIZECUSTOM_H #define SERIALIZECUSTOM_H #include "../BinarySerializer.h" #include <GTMesh/Traits/CustomTypeTraits.h> struct SerializeCustom { template <typename T> using IsBitviseSerializable = Impl::void_t<decltype(BinarySerialize(std::declval<BinarySerializer::ByteContainer&>(), std::declval<const T&>()))>; template <typename T> using IsBitviseDeserializable = Impl::void_t<decltype(BinaryDeserialize(std::declval<BinarySerializer::ByteContainerIterator&>(), std::declval<const T&>()))>; template <typename T> static IsBitviseSerializable<T> serialize(BinarySerializer::ByteContainer& dataContainer, const T& data, ...) { BinarySerialize(dataContainer, data); } template <typename T> static IsBitviseDeserializable<T> deserialize(BinarySerializer::ByteContainerIterator& dataIterator, T& data, ...) { BinaryDeserialize(dataIterator, data); } }; #endif // SERIALIZECUSTOM_H
src/GTMesh/BinarySerializer/Serializers/SerializeIterable.h 0 → 100644 +64 −0 Original line number Diff line number Diff line #ifndef SERIALIZEITERABLE_H #define SERIALIZEITERABLE_H #include <GTMesh/Traits/CustomTypeTraits.h> #include "../BinarySerializer.h" struct SerializeIterable { template <typename T, typename ..., std::enable_if_t<IsIterable<T>::value, bool> = true> static void serialize(std::vector<unsigned char>& dataContainer, const T& data){ BinarySerializer::addNext(dataContainer, data.size()); for (const auto& val : data) { BinarySerializer::addNext(dataContainer, val); } } template <typename T, typename ..., std::enable_if_t<IsIterable<T>::value, bool> = true> static void deserialize(std::vector<unsigned char>::const_iterator& dataIterator, T& data){ decltype(data.size()) size = BinarySerializer::readNext<decltype(data.size())>(dataIterator); if (data.size() != size) { data.resize(size); } for (auto & val : data) { BinarySerializer::readNext(dataIterator, val); } } // TODO think how to deserialize lists and maps }; struct DeserializeAsociativeMap { template <typename T, typename ..., std::enable_if_t<IsIterable<T>::value, bool> = true> static Impl::void_t<typename T::key_type,typename T::mapped_type> deserialize(std::vector<unsigned char>::const_iterator& dataIterator, T& data){ decltype(data.size()) size = BinarySerializer::readNext<decltype(data.size())>(dataIterator); for (decltype(data.size()) i = 0; i < size; i ++) { std::pair<typename T::key_type,typename T::mapped_type> val; BinarySerializer::readNext(dataIterator, val); data.insert(val); } } }; struct DeserializeAsociativeSet { template <typename T, typename ..., std::enable_if_t<IsIterable<T>::value, bool> = true> static Impl::void_t<typename T::key_type> deserialize(std::vector<unsigned char>::const_iterator& dataIterator, T& data){ decltype(data.size()) size = BinarySerializer::readNext<decltype(data.size())>(dataIterator); for (decltype(data.size()) i = 0; i < size; i ++) { typename T::key_type val; BinarySerializer::readNext(dataIterator, val); data.insert(val); } } }; #endif // SERIALIZEITERABLE_H
src/GTMesh/BinarySerializer/Serializers/SerializeSimple.h 0 → 100644 +50 −0 Original line number Diff line number Diff line #ifndef SERIALIZESIMPLE_H #define SERIALIZESIMPLE_H #include <type_traits> #include <vector> #include <stdexcept> namespace Impl { template<typename T> inline constexpr bool IsSimpleSerializable_v = !std::is_class<T>::value; } /** * @brief The SerializeSimple struct serializes simple types as double or int. */ struct SerializeSimple { template <typename T, typename ..., std::enable_if_t<Impl::IsSimpleSerializable_v<T>, bool> = true> static void serialize(std::vector<unsigned char>& dataContainer, const T& data){ const unsigned char* pData = reinterpret_cast<const unsigned char*>(&data); dataContainer.insert(dataContainer.end(), pData, pData + sizeof (T)); } template <typename T, typename ..., std::enable_if_t<Impl::IsSimpleSerializable_v<T>, bool> = true> static void deserialize(std::vector<unsigned char>::const_iterator& dataIterator, T& data){ unsigned char *const pData = reinterpret_cast<unsigned char*>(&data); for (size_t i = 0; i < sizeof (T); i++) { pData[i] = *dataIterator; dataIterator++; } } static void serialize(std::vector<unsigned char>& dataContainer, const bool data){ dataContainer.push_back(data ? 1 : 0); } template <typename T, typename ..., std::enable_if_t<Impl::IsSimpleSerializable_v<T>, bool> = true> static void deserialize(std::vector<unsigned char>::const_iterator& dataIterator, bool& data){ switch (*dataIterator) { case 1: data = true; break; case 0: data = false; break; default: throw std::runtime_error(std::to_string((int)*dataIterator & 0xff) + ": invalid data input for bool 1/0 expected"); } } }; #endif // SERIALIZESIMPLE_H
src/GTMesh/BinarySerializer/Serializers/SerializeTuple.h 0 → 100644 +53 −0 Original line number Diff line number Diff line #ifndef SERIALIZETUPLE_H #define SERIALIZETUPLE_H #include "../BinarySerializer.h" #include <GTMesh/Utils/ConstexprFor.h> #include <tuple> struct SerializeTuple { /** * @brief Python-like print of dictionary pair of key and value. */ template<typename T1, typename T2> static void serialize(BinarySerializer::ByteContainer& dataContainer, const std::pair<T1,T2>& data, ...) { BinarySerializer::addNext(dataContainer, data.first); BinarySerializer::addNext(dataContainer, data.second); } template<typename T1, typename T2> static void deserialize(BinarySerializer::ByteContainerIterator& dataIterator, std::pair<T1,T2>& data, ...) { BinarySerializer::readNext(dataIterator, data.first); BinarySerializer::readNext(dataIterator, data.second); } struct SerializeTupleHelper{ template <unsigned int Index, typename ... TupleTypes> static void exec(BinarySerializer::ByteContainer& dataContainer, const std::tuple<TupleTypes...>& data) { BinarySerializer::addNext(dataContainer, std::get<Index>(data)); } }; template<typename ... TupleTypes> static void serialize(BinarySerializer::ByteContainer& dataContainer, const std::tuple<TupleTypes...>& data, ...) { constexprFor<SerializeTupleHelper, sizeof... (TupleTypes)>(dataContainer, data); } struct DeserializeTupleHelper{ template <unsigned int Index, typename ... TupleTypes> static void exec(BinarySerializer::ByteContainerIterator& dataIterator, std::tuple<TupleTypes...>& data) { BinarySerializer::readNext(dataIterator, std::get<Index>(data)); } }; template<typename ... TupleTypes> static void deserialize(BinarySerializer::ByteContainerIterator& dataIterator, std::tuple<TupleTypes...>& data, ...) { constexprFor<DeserializeTupleHelper, sizeof... (TupleTypes)>(dataIterator, data); } }; #endif // SERIALIZETUPLE_H