<commit_before>#ifndef GCL_SERIALIZATION__
# define GCL_SERIALIZATION__

# include <sstream>
# include <map>
# include "TypeTraits.h"
# include "IO.h"
# include "TemplateMetaProgramming.h"

namespace GCL
{
	namespace Serialization
	{
		struct Interface
		{
			virtual ~Interface() {};

			virtual std::istream & operator>>(std::istream &) = 0;
			virtual std::ostream & operator<<(std::ostream &) const = 0;

			friend inline std::ostream& operator<<(std::ostream & os, const Interface & s)
			{
				s.operator << (os);
				return os;
			}
			friend inline std::istream& operator>>(std::istream & is, Interface & s)
			{
				s.operator >> (is);
				return is;
			}
		};

		template
		<
				typename IO_Policy
			,	typename T_SerializableInterface
			,	typename ... T_SerializableTypes
		>
		struct Serializer
		{
			using T_IOPolicy	= IO_Policy;
			using T_TypeManager = typename TypeTrait::InterfaceIs<T_SerializableInterface>::template OfTypes<T_SerializableTypes...>;
			using _index_type	= typename TypeTrait::InterfaceIs<T_SerializableInterface>::index_type;

			// static typename T_TypeManager::Indexer _typeIndex;

			template <typename T>
			static void							write(std::ostream & os, const T & var)
			{
				T_IOPolicy::write(os, T_TypeManager::T_TypePack::template indexOf<T>()); // throw out_of_range if T is not part of T_SerializableTypes
				// T_IOPolicy::write(os, _typeIndex.indexOf<T>()); 
				os << var;
			}
			static T_SerializableInterface *	read(std::istream & is)
			{
				_index_type typeId;
				T_IOPolicy::read(is, typeId);
				auto & constructor = T_TypeManager::index.at(typeId).defaultConstructeurCallerOp;
				T_SerializableInterface * obj = constructor();
				is >> *obj;
				return obj;
			}
		};

		struct Test
		{
			struct Toto : Serialization::Interface
			{
				int _i;
				~Toto() override {}
				std::istream & operator >> (std::istream & is) override
				{
					IO::Policy::Binary::read(is, _i);
					return is;
				}
				std::ostream & operator << (std::ostream & os) const override
				{
					IO::Policy::Binary::write(os, _i);
					return os;
				}
			};
			struct Titi : Serialization::Interface
			{
				std::string _str;
				~Titi() override {}
				std::istream & operator >> (std::istream & is) override
				{
					IO::Policy::Binary::read(is, _str);
					return is;
				}
				std::ostream & operator << (std::ostream & os) const override
				{
					IO::Policy::Binary::write(os, _str);
					return os;
				}
			};

			using _Serializer = Serializer
			<
				// IO Policy
					IO::Policy::Binary
				// Serializable interface
				,	Serialization::Interface
				// Serializable types
				,	Toto
				,	Titi
			>;

			static bool	Proceed(void)
			{
				std::stringstream ss;
				Titi r_titi1; r_titi1._str = "titi1_str";
				Titi r_titi2; r_titi2._str = "this_is_titi2_str";
				Toto r_toto1; r_toto1._i = 42;
				Toto r_toto2; r_toto2._i = 11223344;

				_Serializer::write(ss, r_titi1);
				_Serializer::write(ss, r_toto1);
				_Serializer::write(ss, r_titi2);
				_Serializer::write(ss, r_toto2);

				Serialization::Interface * w_titi1 = _Serializer::read(ss);
				Serialization::Interface * w_toto1 = _Serializer::read(ss);
				Serialization::Interface * w_titi2 = _Serializer::read(ss);
				Serialization::Interface * w_toto2 = _Serializer::read(ss);

				return (
					r_titi1._str == reinterpret_cast<Titi*>(w_titi1)->_str
					&& r_titi2._str == reinterpret_cast<Titi*>(w_titi2)->_str
					&& r_toto1._i == reinterpret_cast<Toto*>(w_toto1)->_i
					&& r_toto2._i == reinterpret_cast<Toto*>(w_toto2)->_i
					);
			}
		};
	}
}
#endif // GCL_SERIALIZATION__
<commit_msg>New GCL::Serialization implementation. Previous one still exists in GCL::OLD::Serialization<commit_after>#ifndef GCL_SERIALIZATION__
# define GCL_SERIALIZATION__

# include "TypeTraits.h"
# include "IO.h"
# include "TemplateMetaProgramming.h"

# include <sstream>
# include <map>
# include <queue>

namespace GCL
{
	namespace Serialization
	{
		template <class T_Interface>
		struct InterfaceIs
		{
			using _InterfaceType = T_Interface;

			template <typename ...Types>
			struct OfTypes
			{
				// TODO : (void)GCL::TMP::Foreach<Types...>::template Require<IsChildOf<T_Interface>>

				using _TypesPack = typename GCL::TypeTrait::TypePack<Types...>;
				using _ThisType = typename OfTypes<Types...>;

				template <typename T_IO_POlicy = GCL::IO::Policy::Binary>
				struct Writer
				{
					template <typename T>
					static void	write(std::ostream & os, const T & var)
					{
						static_assert(std::is_base_of<_InterfaceType, T>::value, "GCL::Serialization::InterfaceIs<I>::Writer::write<T> : T is not child of I");
						T_IO_POlicy::write(os, _TypesPack::template indexOf<T>());
						os << var;
					}

					explicit	Writer(std::ostream & oStream)
						: _oStream(oStream)
					{}
					template <typename T>
					Writer &	operator<<(const T & element)
					{
						write(_oStream, element);
						return *this;
					}

				private:
					std::ostream & _oStream;
				};
				template <typename T_IO_POlicy = GCL::IO::Policy::Binary>
				struct Reader
				{
					using T_TypeManager = typename TypeTrait::InterfaceIs<_InterfaceType>::template OfTypes<Types...>;

					explicit				Reader(std::istream & istream)
						: _iStream(istream)
					{}

					inline operator bool() const
					{
						return _iStream.operator bool();
					}

					template <typename T>
					static void				read(std::istream & is, T & var)
					{
						size_t typeIndex;
						is >> typeIndex;
						_GCL_ASSERT(_TypesPack::template indexOf<T>() == typeIndex);
						is >> var;
					}
					static _InterfaceType *	read(std::istream & is)
					{
						size_t typeIndex;

						T_IO_POlicy::read(is, typeIndex);
						if (is.eof()) return 0x0;

						auto & constructor = T_TypeManager::index.at(typeIndex).defaultConstructeurCallerOp;
						_InterfaceType * elem = constructor();
						is >> *elem;
						return elem;
					}

					Reader &				operator >> (_InterfaceType *& element)
					{
						_GCL_ASSERT(_iStream);
						element = read(_iStream);
						return *this;
					}
					Reader &				operator >> (std::queue<_InterfaceType*> & elemQueue)
					{
						_GCL_ASSERT(_iStream);
						_InterfaceType * elem{ 0x0 };
						while (*this >> elem)
							elemQueue.push(elem);
						return *this;
					}

				private:
					std::istream & _iStream;
				};
			};
		};

#define GenTestClass(name, type)																			\
	struct name																								\
		: TestInterface																						\
	{																										\
			name() = default;																				\
			name(type value)																				\
			: _value(value)																					\
			{}																								\
			type _value;																					\
																											\
			void	DoStuff(void) const override { std::cout << ""#name##"" " -> value=[" << _value << ']' << std::endl;}\
			std::ostream & operator<<(std::ostream & os) const  override	{ GCL::IO::Policy::Binary::write(os, _value); return os; }	\
			std::istream & operator>>(std::istream & is)		override	{ GCL::IO::Policy::Binary::read (is, _value); return is; }	\
	};

		struct TestInterface
		{
			virtual void DoStuff() const = 0;

			virtual std::istream & operator >> (std::istream &) = 0;
			virtual std::ostream & operator<<(std::ostream &) const = 0;

			friend inline std::ostream& operator<<(std::ostream & os, const TestInterface & s)
			{
				s.operator << (os);
				return os;
			}
			friend inline std::istream& operator >> (std::istream & is, TestInterface & s)
			{
				s.operator >> (is);
				return is;
			}
		};

		GenTestClass(Toto, int)
		GenTestClass(Titi, std::string)
		GenTestClass(Tata, int)
		GenTestClass(Tutu, std::string)

		struct Test
		{
			static bool Proceed(void)
			{
				using Writer = Serialization::InterfaceIs<TestInterface>::OfTypes<Toto, Titi, Tata, Tutu>::Writer<>;

				std::stringstream ss;

				Writer writer(ss);
				writer
					<< Toto{ 42 }
					<< Titi{ "Hello, world" }
					<< Tata{ 130390 }
					<< Tutu{ "Morning' coffee" }
				;
				std::cout << "Serialized : [" << ss.str() << ']' << std::endl;

				using Reader = Serialization::InterfaceIs<TestInterface>::OfTypes<Toto, Titi, Tata, Tutu>::Reader<>;

				try
				{

					Reader			reader(ss);

					std::queue<TestInterface*> elements;
					reader
						>> elements
						;

					while (not elements.empty())
					{
						elements.front()->DoStuff();
						delete elements.front();
						elements.pop();
					}
				}
				catch (const std::exception & ex)
				{
					std::cerr << ex.what() << std::endl;
				}

				return true;
			}
		};
	}

	namespace OLD
	{
		namespace Serialization
		{
			struct Interface
			{
				virtual ~Interface() {};

				virtual std::istream & operator >> (std::istream &) = 0;
				virtual std::ostream & operator<<(std::ostream &) const = 0;

				friend inline std::ostream& operator<<(std::ostream & os, const Interface & s)
				{
					s.operator << (os);
					return os;
				}
				friend inline std::istream& operator >> (std::istream & is, Interface & s)
				{
					s.operator >> (is);
					return is;
				}
			};

			template
				<
				typename IO_Policy
				, typename T_SerializableInterface
				, typename ... T_SerializableTypes
				>
				struct Serializer
			{
				using T_IOPolicy = IO_Policy;
				using T_TypeManager = typename GCL::TypeTrait::InterfaceIs<T_SerializableInterface>::template OfTypes<T_SerializableTypes...>;
				using _index_type = typename GCL::TypeTrait::InterfaceIs<T_SerializableInterface>::index_type;

				// static typename T_TypeManager::Indexer _typeIndex;

				template <typename T>
				static void							write(std::ostream & os, const T & var)
				{
					T_IOPolicy::write(os, T_TypeManager::T_TypePack::template indexOf<T>()); // throw out_of_range if T is not part of T_SerializableTypes
					// T_IOPolicy::write(os, _typeIndex.indexOf<T>()); 
					os << var;
				}
				static T_SerializableInterface *	read(std::istream & is)
				{
					_index_type typeId;
					T_IOPolicy::read(is, typeId);
					auto & constructor = T_TypeManager::index.at(typeId).defaultConstructeurCallerOp;
					T_SerializableInterface * obj = constructor();
					is >> *obj;
					return obj;
				}
			};

			struct Test
			{
				struct Toto : Serialization::Interface
				{
					int _i;
					~Toto() override {}
					std::istream & operator >> (std::istream & is) override
					{
						IO::Policy::Binary::read(is, _i);
						return is;
					}
					std::ostream & operator << (std::ostream & os) const override
					{
						IO::Policy::Binary::write(os, _i);
						return os;
					}
				};
				struct Titi : Serialization::Interface
				{
					std::string _str;
					~Titi() override {}
					std::istream & operator >> (std::istream & is) override
					{
						IO::Policy::Binary::read(is, _str);
						return is;
					}
					std::ostream & operator << (std::ostream & os) const override
					{
						IO::Policy::Binary::write(os, _str);
						return os;
					}
				};

				using _Serializer = Serializer
					<
					// IO Policy
					IO::Policy::Binary
					// Serializable interface
					, Serialization::Interface
					// Serializable types
					, Toto
					, Titi
					>;

				static bool	Proceed(void)
				{
					std::stringstream ss;
					Titi r_titi1; r_titi1._str = "titi1_str";
					Titi r_titi2; r_titi2._str = "this_is_titi2_str";
					Toto r_toto1; r_toto1._i = 42;
					Toto r_toto2; r_toto2._i = 11223344;

					_Serializer::write(ss, r_titi1);
					_Serializer::write(ss, r_toto1);
					_Serializer::write(ss, r_titi2);
					_Serializer::write(ss, r_toto2);

					Serialization::Interface * w_titi1 = _Serializer::read(ss);
					Serialization::Interface * w_toto1 = _Serializer::read(ss);
					Serialization::Interface * w_titi2 = _Serializer::read(ss);
					Serialization::Interface * w_toto2 = _Serializer::read(ss);

					return (
						r_titi1._str == reinterpret_cast<Titi*>(w_titi1)->_str
						&& r_titi2._str == reinterpret_cast<Titi*>(w_titi2)->_str
						&& r_toto1._i == reinterpret_cast<Toto*>(w_toto1)->_i
						&& r_toto2._i == reinterpret_cast<Toto*>(w_toto2)->_i
						);
				}
			};
		}
	}
}
#endif // GCL_SERIALIZATION__

{'fraction_non_alphanumeric': 0.13818930041152264, 'fraction_numerical': 0.007489711934156379, 'mean_word_length': 2.8114805520702637, 'pattern_counts': {'":': 0, '<': 123, '<?xml version=': 0, '>': 115, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7450608', 'n_tokens_mistral': 5356, 'n_tokens_neox': 4053, 'n_words': 808}