From 935bf1944e1ddeaf51fd22cdce04a2a97762890f Mon Sep 17 00:00:00 2001
From: Alberto Nidasio <alberto.nidasio@skywarder.eu>
Date: Sun, 17 Apr 2022 18:48:34 +0200
Subject: [PATCH] [Documentation] Formatted code and slightly improved comments

---
 tscpp/buffer.cpp |  85 +++++++++-------
 tscpp/buffer.h   | 215 ++++++++++++++++++++++------------------
 tscpp/stream.cpp |  81 ++++++++-------
 tscpp/stream.h   | 252 ++++++++++++++++++++++++++---------------------
 4 files changed, 354 insertions(+), 279 deletions(-)

diff --git a/tscpp/buffer.cpp b/tscpp/buffer.cpp
index 2b48417..61e06bb 100644
--- a/tscpp/buffer.cpp
+++ b/tscpp/buffer.cpp
@@ -29,67 +29,80 @@
 
 using namespace std;
 
-namespace tscpp {
+namespace tscpp
+{
 
-int TypePoolBuffer::unserializeUnknownImpl(const char *name, const void *buffer, int bufSize) const
+int TypePoolBuffer::unserializeUnknownImpl(const char *name, const void *buffer,
+                                           int bufSize) const
 {
-    auto it=types.find(name);
-    if(it==types.end()) return UnknownType;
+    auto it = types.find(name);
+    if (it == types.end())
+        return UnknownType;
 
-    if(it->second.size>bufSize) return BufferTooSmall;
+    if (it->second.size > bufSize)
+        return BufferTooSmall;
 
     it->second.usc(buffer);
     return it->second.size;
 }
 
-int serializeImpl(void *buffer, int bufSize, const char *name, const void *data, int size)
+int serializeImpl(void *buffer, int bufSize, const char *name, const void *data,
+                  int size)
 {
-    int nameSize=strlen(name);
-    int serializedSize=nameSize+1+size;
-    if(serializedSize>bufSize) return BufferTooSmall;
+    int nameSize       = strlen(name);
+    int serializedSize = nameSize + 1 + size;
+    if (serializedSize > bufSize)
+        return BufferTooSmall;
 
-    char *buf=reinterpret_cast<char*>(buffer);
-    memcpy(buf,name,nameSize+1); //Copy also the \0
-    memcpy(buf+nameSize+1,data,size);
+    char *buf = reinterpret_cast<char *>(buffer);
+    memcpy(buf, name, nameSize + 1);  // Copy also the \0
+    memcpy(buf + nameSize + 1, data, size);
     return serializedSize;
 }
 
-int unserializeImpl(const char *name, void *data, int size, const void *buffer, int bufSize)
+int unserializeImpl(const char *name, void *data, int size, const void *buffer,
+                    int bufSize)
 {
-    int nameSize=strlen(name);
-    int serializedSize=nameSize+1+size;
-    if(serializedSize>bufSize) return BufferTooSmall;
+    int nameSize       = strlen(name);
+    int serializedSize = nameSize + 1 + size;
+    if (serializedSize > bufSize)
+        return BufferTooSmall;
 
-    const char *buf=reinterpret_cast<const char*>(buffer);
-    if(memcmp(buf,name,nameSize+1)) return WrongType;
+    const char *buf = reinterpret_cast<const char *>(buffer);
+    if (memcmp(buf, name, nameSize + 1))
+        return WrongType;
 
-    //NOTE: we are writing on top of a constructed type without calling its
-    //destructor. However, since it is trivially copyable, we at least aren't
-    //overwriting pointers to allocated memory.
-    memcpy(data,buf+nameSize+1,size);
+    // NOTE: we are writing on top of a constructed type without calling its
+    // destructor. However, since it is trivially copyable, we at least aren't
+    // overwriting pointers to allocated memory.
+    memcpy(data, buf + nameSize + 1, size);
     return serializedSize;
 }
 
-int unserializeUnknown(const TypePoolBuffer& tp, const void *buffer, int bufSize)
+int unserializeUnknown(const TypePoolBuffer &tp, const void *buffer,
+                       int bufSize)
 {
-    const char *buf=reinterpret_cast<const char*>(buffer);
-    int nameSize=strnlen(buf,bufSize);
-    if(nameSize>=bufSize) return BufferTooSmall;
+    const char *buf = reinterpret_cast<const char *>(buffer);
+    int nameSize    = strnlen(buf, bufSize);
+    if (nameSize >= bufSize)
+        return BufferTooSmall;
 
-    const char *name=buf;
-    buf+=nameSize+1;
-    bufSize-=nameSize+1;
-    auto result=tp.unserializeUnknownImpl(name,buf,bufSize);
-    if(result<0) return result;
-    return result+nameSize+1;
+    const char *name = buf;
+    buf += nameSize + 1;
+    bufSize -= nameSize + 1;
+    auto result = tp.unserializeUnknownImpl(name, buf, bufSize);
+    if (result < 0)
+        return result;
+    return result + nameSize + 1;
 }
 
 string peekTypeName(const void *buffer, int bufSize)
 {
-    const char *buf=reinterpret_cast<const char*>(buffer);
-    int nameSize=strnlen(buf,bufSize);
-    if(nameSize>=bufSize) return "";
+    const char *buf = reinterpret_cast<const char *>(buffer);
+    int nameSize    = strnlen(buf, bufSize);
+    if (nameSize >= bufSize)
+        return "";
     return buf;
 }
 
-} //namespace tscpp
+}  // namespace tscpp
diff --git a/tscpp/buffer.h b/tscpp/buffer.h
index 85b7490..e7b96f5 100644
--- a/tscpp/buffer.h
+++ b/tscpp/buffer.h
@@ -27,37 +27,41 @@
 
 #pragma once
 
-#include <type_traits>
-#include <functional>
 #include <cstring>
-#include <string>
+#include <functional>
 #include <map>
+#include <string>
+#include <type_traits>
 
 /**
  * \file buffer.h
- * TSCPP buffer API. This file contains functions to serialize types to raw
- * memory buffers. These classes provide a low level API to serialization.
- * Error reporting is performed through return codes.
- * 
- * NOTE: the serialization format between the buffer and stream API is
+ *
+ * @brief TSCPP buffer API.
+ *
+ * This file contains functions to serialize types to raw memory buffers. These
+ * classes provide a low level API to serialization. Error reporting is
+ * performed through return codes.
+ *
+ * NOTE: The serialization format between the buffer and stream API is
  * interchangeable, so you can for example serialize using the buffer API and
  * unserialize using the stream API.
  */
-
-namespace tscpp {
+namespace tscpp
+{
 
 /**
- * Error codes returned by the buffer API of tscpp
+ * @brief Error codes returned by the buffer API of tscpp.
  */
 enum TscppError
 {
-    BufferTooSmall = -1, ///< Buffer is too small for the given type
-    WrongType      = -2, ///< While unserializing a different type was found
-    UnknownType    = -3  ///< While unserializing the type was not found in the pool
+    BufferTooSmall = -1,  ///< Buffer is too small for the given type
+    WrongType      = -2,  ///< While deserializing a different type was found
+    UnknownType = -3  ///< While deserializing the type wasn't found in the pool
 };
 
 /**
- * Type pool for the TSCPP buffer API.
+ * @brief Type pool for the TSCPP buffer API.
+ *
  * A type pool is a class where you can register types and associate callbacks
  * to them. It is used to unserialize types when you don't know the exact type
  * or order in which types have been serialized.
@@ -66,127 +70,144 @@ class TypePoolBuffer
 {
 public:
     /**
-     * Register a type and the associated callback
-     * \tparam T type to be registered
-     * \param callback callabck to be called whan the given type is unserialized
+     * @brief Register a type and the associated callback.
+     *
+     * \tparam T Type to be registered.
+     * \param callback Callback used when the given type is unserialized.
      */
-    template<typename T>
-    void registerType(std::function<void (T& t)> callback)
-    {
-        #ifndef _MIOSIX
-        static_assert(std::is_trivially_copyable<T>::value,"Type is not trivially copyable");
-        #endif
-        types[typeid(T).name()]=UnserializerImpl(sizeof(T),[=](const void *buffer) {
-            //NOTE: We copy the buffer to respect alignment requirements.
-            //The buffer may not be suitably aligned for the unserialized type
-            //TODO: support classes without default constructor
-            //NOTE: we are writing on top of a constructed type without callingits
-            //destructor. However, since it is trivially copyable, we at least aren't
-            //overwriting pointers to allocated memory.
-            T t;
-            memcpy(&t,buffer,sizeof(T));
-            callback(t);
-        });
-    }
+    template <typename T>
+    void registerType(std::function<void(T &t)> callback);
+
+    int unserializeUnknownImpl(const char *name, const void *buffer,
+                               int bufSize) const;
 
-    /**
-     * \internal
-     */
-    int unserializeUnknownImpl(const char *name, const void *buffer, int bufSize) const;
-    
 private:
-    /**
-     * \internal
-     */
-    class UnserializerImpl
+    class DeserializerImpl
     {
     public:
-        UnserializerImpl() : size(0) {}
-        UnserializerImpl(int size, std::function<void (const void*)> usc) : size(size), usc(usc) {}
+        DeserializerImpl() : size(0) {}
+        DeserializerImpl(int size, std::function<void(const void *)> usc)
+            : size(size), usc(usc)
+        {
+        }
+
         int size;
-        std::function<void (const void*)> usc;
+        std::function<void(const void *)> usc;
     };
 
-    std::map<std::string,UnserializerImpl> types; ///< Registered types
+    std::map<std::string, DeserializerImpl> types;  ///< Registered types
 };
 
-/**
- * \internal
- */
-int serializeImpl(void *buffer, int bufSize, const char *name, const void *data, int size);
+template <typename T>
+void TypePoolBuffer::registerType(std::function<void(T &t)> callback)
+{
+#ifndef _MIOSIX
+    static_assert(std::is_trivially_copyable<T>::value,
+                  "Type is not trivially copyable");
+#endif
+    types[typeid(T).name()] =
+        DeserializerImpl(sizeof(T),
+                         [=](const void *buffer)
+                         {
+                             // NOTE: We copy the buffer to respect
+                             // alignment requirements. The buffer may not
+                             // be suitably aligned for the unserialized
+                             // type.
+                             // TODO: support classes without default
+                             // constructor.
+                             // NOTE: we are writing on top of a
+                             // constructed type without callingits
+                             // destructor. However, since it is trivially
+                             // copyable, we at least aren't overwriting
+                             // pointers to allocated memory.
+                             T t;
+                             memcpy(&t, buffer, sizeof(T));
+                             callback(t);
+                         });
+}
+
+int serializeImpl(void *buffer, int bufSize, const char *name, const void *data,
+                  int size);
 
 /**
- * Serialize a type to a memory buffer
- * \param buffer ponter to the memory buffer where to serialize the type
- * \param bufSize buffer size
- * \param t type to serialize
- * \return the size of the serialized type (which is larger than sizeof(T) due
+ * @brief Serialize a type to a memory buffer.
+ *
+ * \param buffer Pointer to the memory buffer where to serialize the type.
+ * \param bufSize Buffer size.
+ * \param t Type to serialize.
+ * \return The size of the serialized type (which is larger than sizeof(T) due
  * to serialization overhead), or TscppError::BufferTooSmall if the given
  * buffer is too small
  */
-template<typename T>
-int serialize(void *buffer, int bufSize, const T& t)
+template <typename T>
+int serialize(void *buffer, int bufSize, const T &t)
 {
-    #ifndef _MIOSIX
-    static_assert(std::is_trivially_copyable<T>::value,"Type is not trivially copyable");
-    #endif
-    return serializeImpl(buffer,bufSize,typeid(t).name(),&t,sizeof(t));
+#ifndef _MIOSIX
+    static_assert(std::is_trivially_copyable<T>::value,
+                  "Type is not trivially copyable");
+#endif
+    return serializeImpl(buffer, bufSize, typeid(t).name(), &t, sizeof(t));
 }
 
-/**
- * \internal
- */
-int unserializeImpl(const char *name, void *data, int size, const void *buffer, int bufSize);
+int unserializeImpl(const char *name, void *data, int size, const void *buffer,
+                    int bufSize);
 
 /**
- * Unserialize a known type from a memory buffer
- * \param t type to unserialize
- * \param buffer pointer to buffer where the serialized type is
- * \param bufSize buffer size
- * \return the size of the unserialized type (which is larger than sizeof(T) due
+ * @brief Unserialize a known type from a memory buffer.
+ *
+ * \param t Type to unserialize.
+ * \param buffer Pointer to buffer where the serialized type is.
+ * \param bufSize Buffer size.
+ * \return The size of the unserialized type (which is larger than sizeof(T) due
  * to serialization overhead), or TscppError::WrongType if the buffer does
  * not contain the given type or TscppError::BufferTooSmall if the type is
- * truncated, i.e the buffer is smaller tah the serialized type size
+ * truncated, i.e the buffer is smaller tah the serialized type size.
  */
-template<typename T>
-int unserialize(T& t, const void *buffer, int bufSize)
+template <typename T>
+int unserialize(T &t, const void *buffer, int bufSize)
 {
-    #ifndef _MIOSIX
-    static_assert(std::is_trivially_copyable<T>::value,"Type is not trivially copyable");
-    #endif
-    return unserializeImpl(typeid(t).name(),&t,sizeof(t),buffer,bufSize);
+#ifndef _MIOSIX
+    static_assert(std::is_trivially_copyable<T>::value,
+                  "Type is not trivially copyable");
+#endif
+    return unserializeImpl(typeid(t).name(), &t, sizeof(t), buffer, bufSize);
 }
 
 /**
- * Unserialize an unknown type from a memory buffer
- * \param tp type pool where possible serialized types are registered
- * \param buffer pointer to buffer where the serialized type is
- * \param bufSize buffer size
- * \return the size of the unserialized type (which is larger than sizeof(T) due
+ * @brief Unserialize an unknown type from a memory buffer.
+ *
+ * \param tp Type pool where possible serialized types are registered.
+ * \param buffer Pointer to buffer where the serialized type is.
+ * \param bufSize Buffer size.
+ * \return The size of the unserialized type (which is larger than sizeof(T) due
  * to serialization overhead), or TscppError::UnknownType if the pool does
- * not contain the type found in the buffer or TscppError::BufferTooSmall if the 
- * type is truncated, i.e the buffer is smaller tah the serialized type size
+ * not contain the type found in the buffer or TscppError::BufferTooSmall if the
+ * type is truncated, i.e the buffer is smaller tah the serialized type size.
  */
-int unserializeUnknown(const TypePoolBuffer& tp, const void *buffer, int bufSize);
+int unserializeUnknown(const TypePoolBuffer &tp, const void *buffer,
+                       int bufSize);
 
 /**
- * Given a buffer where a type has been serialized, return the C++ mangled
- * name of the serialized type.
+ * @brief Given a buffer where a type has been serialized, return the C++
+ * mangled name of the serialized type.
+ *
  * It is useful when unserialize returns TscppError::WrongType to print an
- * error message with the name of the type in the buffer
+ * error message with the name of the type in the buffer.
+ *
  * \code
  * Foo f;
  * auto result=unserialize(f,buffer,size);
  * if(result==WrongType)
  * {
- *     cerr<<"While unserializing Foo, "<<demangle(peekTypeName(buffer,size))<<" was found\n";
+ *     cerr << "While deserializing Foo, " <<
+ *     demangle(peekTypeName(buffer,size)) << " was found\n";
  * }
  * \endcode
- * \param buffer pointer to buffer where the serialized type is
- * \param bufSize buffer size
- * \return the serialized type name, or "" if the buffer does not contain a type
- * name
+ *
+ * \param buffer Pointer to buffer where the serialized type is.
+ * \param bufSize Buffer size.
+ * \return The serialized type name, or "" if the buffer doesn't contain a name.
  */
 std::string peekTypeName(const void *buffer, int bufSize);
 
-} // namespace tscpp
+}  // namespace tscpp
diff --git a/tscpp/stream.cpp b/tscpp/stream.cpp
index f9df3f4..c95867c 100644
--- a/tscpp/stream.cpp
+++ b/tscpp/stream.cpp
@@ -26,6 +26,7 @@
  ***************************************************************************/
 
 #include "stream.h"
+
 #include <memory>
 #if defined(__GNUC__) && !defined(_MIOSIX)
 #include <cxxabi.h>
@@ -33,75 +34,83 @@
 
 using namespace std;
 
-namespace tscpp {
+namespace tscpp
+{
 
-void TypePoolStream::unserializeUnknownImpl(const string& name, istream& is, streampos pos) const
+void TypePoolStream::unserializeUnknownImpl(const string& name, istream& is,
+                                            streampos pos) const
 {
-    auto it=types.find(name);
-    if(it==types.end())
+    auto it = types.find(name);
+    if (it == types.end())
     {
         is.seekg(pos);
-        throw TscppException("unknown type",name);
+        throw TscppException("unknown type", name);
     }
 
     it->second(is);
 }
 
-void OutputArchive::serializeImpl(const char *name, const void *data, int size)
+void OutputArchive::serializeImpl(const char* name, const void* data, int size)
 {
-    int nameSize=strlen(name);
-    os.write(name,nameSize+1);
-    os.write(reinterpret_cast<const char*>(data),size);
+    int nameSize = strlen(name);
+    os.write(name, nameSize + 1);
+    os.write(reinterpret_cast<const char*>(data), size);
 }
 
-void InputArchive::unserializeImpl(const char *name, void *data, int size)
+void InputArchive::unserializeImpl(const char* name, void* data, int size)
 {
-    auto pos=is.tellg();
-    int nameSize=strlen(name);
-    unique_ptr<char[]> unserializedName(new char[nameSize+1]);
-    is.read(unserializedName.get(),nameSize+1);
-    if(is.eof()) throw TscppException("eof");
+    auto pos     = is.tellg();
+    int nameSize = strlen(name);
+    unique_ptr<char[]> unserializedName(new char[nameSize + 1]);
+    is.read(unserializedName.get(), nameSize + 1);
+    if (is.eof())
+        throw TscppException("eof");
 
-    if(memcmp(unserializedName.get(),name,nameSize+1)) wrongType(pos);
+    if (memcmp(unserializedName.get(), name, nameSize + 1))
+        wrongType(pos);
 
-    //NOTE: we are writing on top of a constructed type without calling its
-    //destructor. However, since it is trivially copyable, we at least aren't
-    //overwriting pointers to allocated memory.
-    is.read(reinterpret_cast<char*>(data),size);
-    if(is.eof()) throw TscppException("eof");
+    // NOTE: We are writing on top of a constructed type without calling its
+    // destructor. However, since it is trivially copyable, we at least aren't
+    // overwriting pointers to allocated memory.
+    is.read(reinterpret_cast<char*>(data), size);
+    if (is.eof())
+        throw TscppException("eof");
 }
 
 void InputArchive::wrongType(streampos pos)
 {
     is.seekg(pos);
     string name;
-    getline(is,name,'\0');
+    getline(is, name, '\0');
     is.seekg(pos);
-    throw TscppException("wrong type",name);
+    throw TscppException("wrong type", name);
 }
 
 void UnknownInputArchive::unserialize()
 {
-    auto pos=is.tellg();
+    auto pos = is.tellg();
     string name;
-    getline(is,name,'\0');
-    if(is.eof()) throw TscppException("eof");
+    getline(is, name, '\0');
+    if (is.eof())
+        throw TscppException("eof");
 
-    tp.unserializeUnknownImpl(name,is,pos);
+    tp.unserializeUnknownImpl(name, is, pos);
 }
 
 string demangle(const string& name)
 {
-    #if defined(__GNUC__) && !defined(_MIOSIX)
-    string result=name;
+#if defined(__GNUC__) && !defined(_MIOSIX)
+    string result = name;
     int status;
-    char* demangled=abi::__cxa_demangle(name.c_str(),NULL,0,&status);
-    if(status==0 && demangled) result=demangled;
-    if(demangled) free(demangled);
+    char* demangled = abi::__cxa_demangle(name.c_str(), NULL, 0, &status);
+    if (status == 0 && demangled)
+        result = demangled;
+    if (demangled)
+        free(demangled);
     return result;
-    #else
-    return name; //Demangle not supported
-    #endif
+#else
+    return name;  // Demangle not supported
+#endif
 }
 
-} //namespace tscpp
+}  // namespace tscpp
diff --git a/tscpp/stream.h b/tscpp/stream.h
index 0db7b3f..68daa88 100644
--- a/tscpp/stream.h
+++ b/tscpp/stream.h
@@ -27,63 +27,67 @@
 
 /**
  * \file stream.h
- * TSCPP stream API. This file contains classes to serialize types to std
+ *
+ * @brief TSCPP stream API.
+ *
+ * This file contains classes to serialize types to std
  * streams. These classes provide a high level API compatible with the C++ stl.
  * Error reporting is performed through exceptions.
- * 
- * NOTE: the serialization format between the buffer and stream API is
+ *
+ * NOTE: The serialization format between the buffer and stream API is
  * interchangeable, so you can for example serialize using the buffer API and
  * unserialize using the stream API.
  */
 
 #pragma once
 
-#include <type_traits>
+#include <cstring>
 #include <functional>
-#include <stdexcept>
-#include <ostream>
 #include <istream>
-#include <cstring>
-#include <string>
 #include <map>
+#include <ostream>
+#include <stdexcept>
+#include <string>
+#include <type_traits>
 
-namespace tscpp {
+namespace tscpp
+{
 
 /**
- * Exception class thrown by the input archives
+ * Exception class thrown by the input archives.
  */
 class TscppException : public std::runtime_error
 {
 public:
-    /**
-     * \internal
-     */
     TscppException(const std::string& what) : runtime_error(what) {}
-    
-    /**
-     * \internal
-     */
+
     TscppException(const std::string& what, const std::string& n)
-        : runtime_error(what), n(n) {}
-    
+        : runtime_error(what), n(n)
+    {
+    }
+
     /**
      * If the exception is thrown because an unknown/unexpected type has been
      * found in the input stream, this member function allows to access the
      * mangled type name.
-     * It is useful to print an error message with the name of the type in the
-     * stream
+     * It is useful to print an error message with the name of the type found in
+     * the stream.
+     *
      * \code
      * InputArchive ia(is);
      * Foo f;
      * try {
-     *     ia>>f;
+     *     ia >> f;
      * } catch(TscppException& ex) {
      *     if(ex.name().empty()==false)
-     *         cerr<<"While unserializing Foo, "<<demangle(ex.name())<<" was found\n";
-     *     else cerr<<ex.what()<<endl;
+     *         cerr << "While deserializing Foo, " << demangle(ex.name()) << "
+     * was found\n";
+     *     else
+     *         cerr << ex.what() << endl;
      * }
      * \endcode
-     * \return the serialized type name, or "" if eof was found
+     *
+     * \return The serialized type name or "" for other errors was found.
      */
     std::string name() const { return n; }
 
@@ -92,7 +96,8 @@ private:
 };
 
 /**
- * Type pool for the TSCPP stream API.
+ * @brief Type pool for the TSCPP stream API.
+ *
  * A type pool is a class where you can register types and associate callbacks
  * to them. It is used to unserialize types when you don't know the exact type
  * or order in which types have been serialized.
@@ -101,132 +106,154 @@ class TypePoolStream
 {
 public:
     /**
-     * Register a type and the associated callback
-     * \tparam T type to be registered
-     * \param callback callabck to be called whan the given type is unserialized
+     * @brief Register a type and the associated callback.
+     *
+     * The type to register must have a default constructor defined.
+     *
+     * \tparam T Type to be registered.
+     * \param callback Callback used when the given type is unserialized.
      */
-    template<typename T>
-    void registerType(std::function<void (T& t)> callback)
-    {
-        #ifndef _MIOSIX
-        static_assert(std::is_trivially_copyable<T>::value,"Type is not trivially copyable");
-        #endif
-        types[typeid(T).name()]=[=](std::istream& is) {
-            //NOTE: We copy the buffer to respect alignment requirements.
-            //The buffer may not be suitably aligned for the unserialized type
-            //TODO: support classes without default constructor
-            //NOTE: we are writing on top of a constructed type without calling its
-            //destructor. However, since it is trivially copyable, we at least aren't
-            //overwriting pointers to allocated memory.
-            T t;
-            is.read(reinterpret_cast<char*>(&t),sizeof(T));
-            if(is.eof()) throw TscppException("eof");
-            callback(t);
-        };
-    }
-    
-    /**
-     * \internal
-     */
-    void unserializeUnknownImpl(const std::string& name, std::istream& is, std::streampos pos) const;
-    
+    template <typename T>
+    void registerType(std::function<void(T& t)> callback);
+
+    void unserializeUnknownImpl(const std::string& name, std::istream& is,
+                                std::streampos pos) const;
+
 private:
-    std::map<std::string,std::function<void (std::istream&)>> types; ///< Registered types
+    ///< Registered types serialized name and callback function
+    std::map<std::string, std::function<void(std::istream&)>> types;
 };
 
+template <typename T>
+void TypePoolStream::registerType(std::function<void(T& t)> callback)
+{
+#ifndef _MIOSIX
+    static_assert(std::is_trivially_copyable<T>::value,
+                  "Type is not trivially copyable");
+#endif
+    types[typeid(T).name()] = [=](std::istream& is)
+    {
+        // NOTE: We copy the buffer to respect alignment requirements.
+        // The buffer may not be suitably aligned for the unserialized type
+        // TODO: support classes without default constructor
+        // NOTE: we are writing on top of a constructed type without calling
+        // its destructor. However, since it is trivially copyable, we at
+        // least aren't overwriting pointers to allocated memory.
+        T t;
+        is.read(reinterpret_cast<char*>(&t), sizeof(T));
+        if (is.eof())
+            throw TscppException("eof");
+        callback(t);
+    };
+}
+
 /**
- * The output archive.
- * This class allows to serialize objects to any ostream using the familiar
- * << syntax
+ * @brief The output archive.
+ *
+ * This class allows to serialize objects to any ostream using the << operator.
  */
 class OutputArchive
 {
 public:
     /**
-     * Constructor
-     * \param os ostream where srialized types will be written
+     * \param os Output stream where serialized types will be written.
      */
     OutputArchive(std::ostream& os) : os(os) {}
 
     /**
-     * \internal
+     * @brief Actual implementation of the serialization.
+     *
+     * Saves on the output stream the name followed by the data.
+     *
+     * @param name Type name saved before the data.
+     * @param data Type data
+     * @param size Size of the data
      */
-    void serializeImpl(const char *name, const void *data, int size);
+    void serializeImpl(const char* name, const void* data, int size);
 
 private:
-    OutputArchive(const OutputArchive&)=delete;
-    OutputArchive& operator=(const OutputArchive&)=delete;
+    OutputArchive(const OutputArchive&) = delete;
+    OutputArchive& operator=(const OutputArchive&) = delete;
 
     std::ostream& os;
 };
 
 /**
- * Serialize a type
- * \param oa archive where the type will be serialized
- * \param t type to serialize
+ * @brief Serialize a type.
+ *
+ * \param oa Archive where the type will be serialized.
+ * \param t Type to serialize.
  */
-template<typename T>
+template <typename T>
 OutputArchive& operator<<(OutputArchive& oa, const T& t)
 {
-    #ifndef _MIOSIX
-    static_assert(std::is_trivially_copyable<T>::value,"Type is not trivially copyable");
-    #endif
-    oa.serializeImpl(typeid(t).name(),&t,sizeof(t));
+#ifndef _MIOSIX
+    static_assert(std::is_trivially_copyable<T>::value,
+                  "Type is not trivially copyable");
+#endif
+    oa.serializeImpl(typeid(t).name(), &t, sizeof(t));
     return oa;
 }
 
 /**
- * The input archive.
+ * @brief The input archive.
+ *
  * This class allows to unserialize types from a stream, as long as you know
  * what types have been serialized in which order. Otherwise have a look at
  * UnknownInputArchive.
- * To unserialize, use the familiar >> syntax.
+ *
+ * To unserialize, use the >> operator.
  */
 class InputArchive
 {
 public:
     /**
-     * Constructor
-     * \param is istream where srialized types will be read
+     * \param is Input stream where serialized types will be read.
      */
     InputArchive(std::istream& is) : is(is) {}
 
     /**
-     * \internal
+     * @brief Actual implementation of the deserialization.
+     *
+     * Reads, from the input stream, the name and the data.
+     *
+     * @param name Type name to read before the data.
+     * @param data Pointer where to save the type data.
+     * @param size Size of the data.
      */
-    void unserializeImpl(const char *name, void *data, int size);
+    void unserializeImpl(const char* name, void* data, int size);
 
 private:
-    InputArchive(const InputArchive&)=delete;
-    InputArchive& operator=(const InputArchive&)=delete;
-    
-    /**
-     * \internal
-     */
+    InputArchive(const InputArchive&) = delete;
+    InputArchive& operator=(const InputArchive&) = delete;
+
     void wrongType(std::streampos pos);
 
     std::istream& is;
 };
 
 /**
- * Unserialize a type
- * \param ia archive where the type has been serialized
- * \param t type to unserialize
- * \throws TscppException if the type found in the stream is not the one
- * expected, or if the stream eof is found
+ * @brief Unserialize a type.
+ *
+ * \param ia Archive where the type has been serialized.
+ * \param t Type to unserialize.
+ * \throws Throws a TscppException if the type found in the stream is not the
+ * one expected, or if the stream eof is found.
  */
-template<typename T>
+template <typename T>
 InputArchive& operator>>(InputArchive& ia, T& t)
 {
-    #ifndef _MIOSIX
-    static_assert(std::is_trivially_copyable<T>::value,"Type is not trivially copyable");
-    #endif
-    ia.unserializeImpl(typeid(t).name(),&t,sizeof(t));
+#ifndef _MIOSIX
+    static_assert(std::is_trivially_copyable<T>::value,
+                  "Type is not trivially copyable");
+#endif
+    ia.unserializeImpl(typeid(t).name(), &t, sizeof(t));
     return ia;
 }
 
 /**
- * The unknown input archive.
+ * @brief The unknown input archive.
+ *
  * This class allows to unserialize types from a stream which have been
  * serialized in an unknown order.
  */
@@ -234,36 +261,41 @@ class UnknownInputArchive
 {
 public:
     /**
-     * Constructor
-     * \param is istream where srialized types will be read
+     * \param is Input stream where serialized types will be read.
      * \param tp TypePool containing the registered types and callbacks that
-     * will be called as types are unserialized
+     * will be called as types are unserialized.
      */
-    UnknownInputArchive(std::istream& is, const TypePoolStream& tp) : is(is), tp(tp) {}
+    UnknownInputArchive(std::istream& is, const TypePoolStream& tp)
+        : is(is), tp(tp)
+    {
+    }
 
     /**
-     * Unserialize one type from the input stream, calling the corresponding
-     * callback in the TypePool
-     * \throws TscppException if the type found in the stream has not been
-     * registred in the TypePool or if the stream eof is found
+     * @brief Unserialize one type from the input stream, calling the
+     * corresponding callback registered in the TypePool.
+     *
+     * \throws Throws a TscppException if the type found in the stream has not
+     * been registred in the TypePool or if the stream eof is found.
      */
     void unserialize();
 
 private:
-    UnknownInputArchive(const UnknownInputArchive&)=delete;
-    UnknownInputArchive& operator=(const UnknownInputArchive&)=delete;
+    UnknownInputArchive(const UnknownInputArchive&) = delete;
+    UnknownInputArchive& operator=(const UnknownInputArchive&) = delete;
 
     std::istream& is;
     const TypePoolStream& tp;
 };
 
 /**
- * Demangle a C++ name. Useful for printing type names in error logs.
- * This function may not be supported in all platforms, in this case it returns
+ * @brief Demangle a C++ name. Useful for printing type names in error logs.
+ *
+ * This function may not be supported on all platforms, in this case it returns
  * the the same string passed as a parameter.
- * \param name name to demangle
- * \return the demangled name
+ *
+ * \param name Name to demangle.
+ * \return The demangled name.
  */
 std::string demangle(const std::string& name);
 
-} // namespace tscpp
+}  // namespace tscpp
-- 
GitLab