From abe5b0649d3b5ddc4e1e61577fc0dbc5218346d6 Mon Sep 17 00:00:00 2001 From: Terraneo Federico <fede.tft@miosix.org> Date: Mon, 7 May 2018 09:53:17 +0200 Subject: [PATCH] Separate stream and buffer API in different headers --- buffer.cpp | 95 ++++++++++++++++ buffer.h | 192 +++++++++++++++++++++++++++++++++ examples/1_stream_known.cpp | 2 +- examples/2_stream_unknown.cpp | 4 +- examples/3_buffer_known.cpp | 2 +- examples/4_buffer_unknown.cpp | 4 +- examples/5_stream_failtest.cpp | 4 +- examples/6_buffer_failtest.cpp | 4 +- examples/Makefile | 14 +-- tscpp.cpp => stream.cpp | 93 +++------------- tscpp.h => stream.h | 130 +++++----------------- 11 files changed, 344 insertions(+), 200 deletions(-) create mode 100644 buffer.cpp create mode 100644 buffer.h rename tscpp.cpp => stream.cpp (67%) rename tscpp.h => stream.h (70%) diff --git a/buffer.cpp b/buffer.cpp new file mode 100644 index 0000000..2b48417 --- /dev/null +++ b/buffer.cpp @@ -0,0 +1,95 @@ +/*************************************************************************** + * Copyright (C) 2018 by Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * As a special exception, if other files instantiate templates or use * + * macros or inline functions from this file, or you compile this file * + * and link it with other works to produce a work based on this file, * + * this file does not by itself cause the resulting work to be covered * + * by the GNU General Public License. However the source code for this * + * file must still be made available in accordance with the GNU General * + * Public License. This exception does not invalidate any other reasons * + * why a work based on this file might be covered by the GNU General * + * Public License. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#include "buffer.h" + +using namespace std; + +namespace tscpp { + +int TypePoolBuffer::unserializeUnknownImpl(const char *name, const void *buffer, int bufSize) const +{ + auto it=types.find(name); + if(it==types.end()) return UnknownType; + + 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 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); + return serializedSize; +} + +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; + + 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); + return serializedSize; +} + +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 *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 ""; + return buf; +} + +} //namespace tscpp diff --git a/buffer.h b/buffer.h new file mode 100644 index 0000000..85b7490 --- /dev/null +++ b/buffer.h @@ -0,0 +1,192 @@ +/*************************************************************************** + * Copyright (C) 2018 by Terraneo Federico * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * As a special exception, if other files instantiate templates or use * + * macros or inline functions from this file, or you compile this file * + * and link it with other works to produce a work based on this file, * + * this file does not by itself cause the resulting work to be covered * + * by the GNU General Public License. However the source code for this * + * file must still be made available in accordance with the GNU General * + * Public License. This exception does not invalidate any other reasons * + * why a work based on this file might be covered by the GNU General * + * Public License. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see <http://www.gnu.org/licenses/> * + ***************************************************************************/ + +#pragma once + +#include <type_traits> +#include <functional> +#include <cstring> +#include <string> +#include <map> + +/** + * \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 + * interchangeable, so you can for example serialize using the buffer API and + * unserialize using the stream API. + */ + +namespace tscpp { + +/** + * 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 +}; + +/** + * 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. + */ +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 + */ + 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); + }); + } + + /** + * \internal + */ + int unserializeUnknownImpl(const char *name, const void *buffer, int bufSize) const; + +private: + /** + * \internal + */ + class UnserializerImpl + { + public: + UnserializerImpl() : size(0) {} + UnserializerImpl(int size, std::function<void (const void*)> usc) : size(size), usc(usc) {} + int size; + std::function<void (const void*)> usc; + }; + + std::map<std::string,UnserializerImpl> types; ///< Registered types +}; + +/** + * \internal + */ +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 + * 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) +{ + #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); + +/** + * 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 + */ +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); +} + +/** + * 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 + */ +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. + * It is useful when unserialize returns TscppError::WrongType to print an + * 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"; + * } + * \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 + */ +std::string peekTypeName(const void *buffer, int bufSize); + +} // namespace tscpp diff --git a/examples/1_stream_known.cpp b/examples/1_stream_known.cpp index 67355d1..886142f 100644 --- a/examples/1_stream_known.cpp +++ b/examples/1_stream_known.cpp @@ -2,7 +2,7 @@ #include <iostream> #include <sstream> #include <cassert> -#include <tscpp.h> +#include <tscpp/stream.h> #include "types.h" using namespace std; diff --git a/examples/2_stream_unknown.cpp b/examples/2_stream_unknown.cpp index 8ec5340..83fb8f6 100644 --- a/examples/2_stream_unknown.cpp +++ b/examples/2_stream_unknown.cpp @@ -3,7 +3,7 @@ #include <sstream> #include <cassert> #include <cstdlib> -#include <tscpp.h> +#include <tscpp/stream.h> #include "types.h" using namespace std; @@ -17,7 +17,7 @@ int main() MiscData md(p2d,p3d,12,-1); //Prepare a type pool for unserialization - TypePool tp; + TypePoolStream tp; tp.registerType<Point2d>([&](Point2d& t) { cout<<"Found a Point2d"<<endl; diff --git a/examples/3_buffer_known.cpp b/examples/3_buffer_known.cpp index aaa82f6..be4669c 100644 --- a/examples/3_buffer_known.cpp +++ b/examples/3_buffer_known.cpp @@ -1,7 +1,7 @@ #include <iostream> #include <cassert> -#include <tscpp.h> +#include <tscpp/buffer.h> #include "types.h" using namespace std; diff --git a/examples/4_buffer_unknown.cpp b/examples/4_buffer_unknown.cpp index aa32d37..1560368 100644 --- a/examples/4_buffer_unknown.cpp +++ b/examples/4_buffer_unknown.cpp @@ -2,7 +2,7 @@ #include <iostream> #include <cassert> #include <cstdlib> -#include <tscpp.h> +#include <tscpp/buffer.h> #include "types.h" using namespace std; @@ -16,7 +16,7 @@ int main() MiscData md(p2d,p3d,12,-1); //Prepare a type pool for unserialization - TypePool tp; + TypePoolBuffer tp; tp.registerType<Point2d>([&](Point2d& t) { cout<<"Found a Point2d"<<endl; diff --git a/examples/5_stream_failtest.cpp b/examples/5_stream_failtest.cpp index cdbb7ce..582ef7d 100644 --- a/examples/5_stream_failtest.cpp +++ b/examples/5_stream_failtest.cpp @@ -2,7 +2,7 @@ #include <iostream> #include <sstream> #include <cassert> -#include <tscpp.h> +#include <tscpp/stream.h> #include "types.h" using namespace std; @@ -67,7 +67,7 @@ int main() } } - TypePool tp; + TypePoolStream tp; tp.registerType<Point2d>([&](Point2d& t) { assert(false); }); tp.registerType<Point3d>([&](Point3d& t) { assert(false); }); diff --git a/examples/6_buffer_failtest.cpp b/examples/6_buffer_failtest.cpp index a2b5784..c222823 100644 --- a/examples/6_buffer_failtest.cpp +++ b/examples/6_buffer_failtest.cpp @@ -2,7 +2,7 @@ #include <iostream> #include <sstream> #include <cassert> -#include <tscpp.h> +#include <tscpp/buffer.h> #include "types.h" using namespace std; @@ -41,7 +41,7 @@ int main() assert(q.x==0 && q.y==0); } - TypePool tp; + TypePoolBuffer tp; tp.registerType<Point2d>([&](Point2d& t) { assert(false); }); tp.registerType<Point3d>([&](Point3d& t) { assert(false); }); diff --git a/examples/Makefile b/examples/Makefile index ab098d7..9134e38 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,14 +1,14 @@ CXX = g++ -CXXFLAGS = -std=c++11 -g -O0 -fsanitize=address -Wall -I.. +CXXFLAGS = -std=c++11 -g -O0 -fsanitize=address -Wall -I../.. all: - $(CXX) $(CXXFLAGS) 1_stream_known.cpp ../tscpp.cpp -o 1_stream_known - $(CXX) $(CXXFLAGS) 2_stream_unknown.cpp ../tscpp.cpp -o 2_stream_unknown - $(CXX) $(CXXFLAGS) 3_buffer_known.cpp ../tscpp.cpp -o 3_buffer_known - $(CXX) $(CXXFLAGS) 4_buffer_unknown.cpp ../tscpp.cpp -o 4_buffer_unknown - $(CXX) $(CXXFLAGS) 5_stream_failtest.cpp ../tscpp.cpp -o 5_stream_failtest - $(CXX) $(CXXFLAGS) 6_buffer_failtest.cpp ../tscpp.cpp -o 6_buffer_failtest + $(CXX) $(CXXFLAGS) 1_stream_known.cpp ../stream.cpp -o 1_stream_known + $(CXX) $(CXXFLAGS) 2_stream_unknown.cpp ../stream.cpp -o 2_stream_unknown + $(CXX) $(CXXFLAGS) 3_buffer_known.cpp ../buffer.cpp -o 3_buffer_known + $(CXX) $(CXXFLAGS) 4_buffer_unknown.cpp ../buffer.cpp -o 4_buffer_unknown + $(CXX) $(CXXFLAGS) 5_stream_failtest.cpp ../stream.cpp -o 5_stream_failtest + $(CXX) $(CXXFLAGS) 6_buffer_failtest.cpp ../buffer.cpp -o 6_buffer_failtest ./1_stream_known ./2_stream_unknown ./3_buffer_known diff --git a/tscpp.cpp b/stream.cpp similarity index 67% rename from tscpp.cpp rename to stream.cpp index 28fbd93..ce88222 100644 --- a/tscpp.cpp +++ b/stream.cpp @@ -25,7 +25,7 @@ * along with this program; if not, see <http://www.gnu.org/licenses/> * ***************************************************************************/ -#include "tscpp.h" +#include "stream.h" #include <memory> #if defined(__GNUC__) && !defined(_MIOSIX) #include <cxxabi.h> @@ -35,18 +35,7 @@ using namespace std; namespace tscpp { -int TypePool::unserializeUnknownImpl(const char *name, const void *buffer, int bufSize) const -{ - auto it=types.find(name); - if(it==types.end()) return UnknownType; - - if(it->second.size>bufSize) return BufferTooSmall; - - it->second.usc(buffer); - return it->second.size; -} - -void TypePool::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()) { @@ -60,70 +49,6 @@ void TypePool::unserializeUnknownImpl(const string& name, istream& is, streampos it->second.usc(unserialized.get()); } -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; - - 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 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; - - //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 TypePool& 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 *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 ""; - return buf; -} - -string demangle(const string& 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); - return result; - #else - return name; //Demangle not supported - #endif -} - void OutputArchive::serializeImpl(const char *name, const void *data, int size) { int nameSize=strlen(name); @@ -167,4 +92,18 @@ void UnknownInputArchive::unserialize() tp.unserializeUnknownImpl(name,is,pos); } +string demangle(const string& 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); + return result; + #else + return name; //Demangle not supported + #endif +} + } //namespace tscpp diff --git a/tscpp.h b/stream.h similarity index 70% rename from tscpp.h rename to stream.h index e871c63..6a026c3 100644 --- a/tscpp.h +++ b/stream.h @@ -25,6 +25,17 @@ * along with this program; if not, see <http://www.gnu.org/licenses/> * ***************************************************************************/ +/** + * \file stream.h + * 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 + * interchangeable, so you can for example serialize using the buffer API and + * unserialize using the stream API. + */ + #pragma once #include <type_traits> @@ -39,21 +50,12 @@ namespace tscpp { /** - * 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 -}; - -/** + * 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. */ -class TypePool +class TypePoolStream { public: /** @@ -79,11 +81,6 @@ public: callback(t); }); } - - /** - * \internal - */ - int unserializeUnknownImpl(const char *name, const void *buffer, int bufSize) const; /** * \internal @@ -106,94 +103,6 @@ private: std::map<std::string,UnserializerImpl> types; ///< Registered types }; -/** - * \internal - */ -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 - * 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) -{ - #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); - -/** - * 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 - */ -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); -} - -/** - * 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 - */ -int unserializeUnknown(const TypePool& tp, const void *buffer, int bufSize); - -/** - * 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 - * \code - * Foo f; - * auto result=unserialize(f,buffer,size); - * if(result==WrongType) - * { - * cerr<<"While unserializing 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 - */ -std::string peekTypeName(const void *buffer, int bufSize); - -/** - * 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 - * the the same string passed as a parameter. - * \param name name to demangle - * \return the demangled name - */ -std::string demangle(const std::string& name); - /** * The output archive. * This class allows to serialize objects to any ostream using the familiar @@ -297,7 +206,7 @@ public: * Constructor * \param os ostream where srialized types will be written */ - UnknownInputArchive(std::istream& is, const TypePool& 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 @@ -312,7 +221,7 @@ private: UnknownInputArchive& operator=(const UnknownInputArchive&)=delete; std::istream& is; - const TypePool& tp; + const TypePoolStream& tp; }; /** @@ -357,4 +266,13 @@ private: std::string n; }; +/** + * 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 + * the the same string passed as a parameter. + * \param name name to demangle + * \return the demangled name + */ +std::string demangle(const std::string& name); + } // namespace tscpp -- GitLab