Skip to content
Snippets Groups Projects
Commit 6ae53573 authored by Federico's avatar Federico
Browse files

Added exceptions to InputArchive

parent f3530e05
No related branches found
No related tags found
No related merge requests found
...@@ -90,7 +90,7 @@ string peekTypeName(const void *buffer, int bufSize) ...@@ -90,7 +90,7 @@ string peekTypeName(const void *buffer, int bufSize)
{ {
const char *buf=reinterpret_cast<const char*>(buffer); const char *buf=reinterpret_cast<const char*>(buffer);
int nameSize=strnlen(buf,bufSize); int nameSize=strnlen(buf,bufSize);
if(nameSize>=bufSize) return "<corrupted>"; if(nameSize>=bufSize) return "";
return buf; return buf;
} }
...@@ -117,30 +117,31 @@ void OutputArchive::serializeImpl(const char *name, const void *data, int size) ...@@ -117,30 +117,31 @@ void OutputArchive::serializeImpl(const char *name, const void *data, int 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(); pos=is.tellg();
int nameSize=strlen(name); int nameSize=strlen(name);
unique_ptr<char[]> unserializedName(new char[nameSize+1]); unique_ptr<char[]> unserializedName(new char[nameSize+1]);
is.read(unserializedName.get(),nameSize+1); is.read(unserializedName.get(),nameSize+1);
if(is.eof()) if(is.eof()) errorImpl("eof");
{
is.seekg(pos);
throw 1; //FIXME
}
if(memcmp(unserializedName.get(),name,nameSize+1)) if(memcmp(unserializedName.get(),name,nameSize+1))
{ errorImpl("wrong type found",true);
is.seekg(pos);
throw 2; //FIXME
}
//NOTE: we are writing on top of a constructed type without calling its //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 //destructor. However, since it is trivially copyable, we at least aren't
//overwriting pointers to allocated memory. //overwriting pointers to allocated memory.
is.read(reinterpret_cast<char*>(data),size); is.read(reinterpret_cast<char*>(data),size);
if(is.eof()) if(is.eof()) errorImpl("eof");
}
void InputArchive::errorImpl(const string& errorStr, bool printName)
{ {
is.seekg(pos); is.seekg(pos);
throw 3; //FIXME if(printName==false) throw TscppException(errorStr);
else {
string type;
getline(is,type,'\0');
is.seekg(pos);
throw TscppException(errorStr,type);
} }
} }
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <type_traits> #include <type_traits>
#include <functional> #include <functional>
#include <stdexcept>
#include <ostream> #include <ostream>
#include <istream> #include <istream>
#include <cstring> #include <cstring>
...@@ -174,8 +175,8 @@ int unserializeUnknown(const TypePool& tp, const void *buffer, int bufSize); ...@@ -174,8 +175,8 @@ int unserializeUnknown(const TypePool& tp, const void *buffer, int bufSize);
* \endcode * \endcode
* \param buffer pointer to buffer where the serialized type is * \param buffer pointer to buffer where the serialized type is
* \param bufSize buffer size * \param bufSize buffer size
* \return the serialized type name, or "<corrupted>" if the buffer does not * \return the serialized type name, or "" if the buffer does not contain a type
* contain a type name * name
*/ */
std::string peekTypeName(const void *buffer, int bufSize); std::string peekTypeName(const void *buffer, int bufSize);
...@@ -250,17 +251,25 @@ public: ...@@ -250,17 +251,25 @@ public:
*/ */
void unserializeImpl(const char *name, void *data, int size); void unserializeImpl(const char *name, void *data, int size);
/**
* \internal
*/
void errorImpl(const std::string& errorStr, bool printName=false);
private: private:
InputArchive(const InputArchive&)=delete; InputArchive(const InputArchive&)=delete;
InputArchive& operator=(const InputArchive&)=delete; InputArchive& operator=(const InputArchive&)=delete;
std::istream& is; std::istream& is;
std::streampos pos;
}; };
/** /**
* Unserialize a type * Unserialize a type
* \param ia archive where the type has been serialized * \param ia archive where the type has been serialized
* \param t type to unserialize * \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
*/ */
template<typename T> template<typename T>
InputArchive& operator>>(InputArchive& ia, T& t) InputArchive& operator>>(InputArchive& ia, T& t)
...@@ -272,4 +281,45 @@ InputArchive& operator>>(InputArchive& ia, T& t) ...@@ -272,4 +281,45 @@ InputArchive& operator>>(InputArchive& ia, T& t)
return ia; return ia;
} }
/**
* 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& t)
: runtime_error(what), t(t) {}
/**
* 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
* \code
* InputArchive ia(is);
* Foo f;
* try {
* ia>>f;
* } catch(TscppException& ex) {
* if(ex.type().empty()==false)
* cerr<<"While unserializing Foo, "<<demangle(ex.type())<<" was found\n";
* }
* \endcode
* \return the serialized type name, or "" if eof was found
*/
std::string type() const { return t; }
private:
std::string t;
};
} // namespace tscpp } // namespace tscpp
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment