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)
{
const char *buf=reinterpret_cast<const char*>(buffer);
int nameSize=strnlen(buf,bufSize);
if(nameSize>=bufSize) return "<corrupted>";
if(nameSize>=bufSize) return "";
return buf;
}
......@@ -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)
{
auto pos=is.tellg();
pos=is.tellg();
int nameSize=strlen(name);
unique_ptr<char[]> unserializedName(new char[nameSize+1]);
is.read(unserializedName.get(),nameSize+1);
if(is.eof())
{
is.seekg(pos);
throw 1; //FIXME
}
if(is.eof()) errorImpl("eof");
if(memcmp(unserializedName.get(),name,nameSize+1))
{
is.seekg(pos);
throw 2; //FIXME
}
errorImpl("wrong type found",true);
//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())
if(is.eof()) errorImpl("eof");
}
void InputArchive::errorImpl(const string& errorStr, bool printName)
{
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 @@
#include <type_traits>
#include <functional>
#include <stdexcept>
#include <ostream>
#include <istream>
#include <cstring>
......@@ -174,8 +175,8 @@ int unserializeUnknown(const TypePool& tp, const void *buffer, int bufSize);
* \endcode
* \param buffer pointer to buffer where the serialized type is
* \param bufSize buffer size
* \return the serialized type name, or "<corrupted>" if the buffer does not
* contain a type name
* \return the serialized type name, or "" if the buffer does not contain a type
* name
*/
std::string peekTypeName(const void *buffer, int bufSize);
......@@ -250,17 +251,25 @@ public:
*/
void unserializeImpl(const char *name, void *data, int size);
/**
* \internal
*/
void errorImpl(const std::string& errorStr, bool printName=false);
private:
InputArchive(const InputArchive&)=delete;
InputArchive& operator=(const InputArchive&)=delete;
std::istream& is;
std::streampos pos;
};
/**
* 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
*/
template<typename T>
InputArchive& operator>>(InputArchive& ia, T& t)
......@@ -272,4 +281,45 @@ InputArchive& operator>>(InputArchive& ia, T& t)
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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment