#ifndef __Exception__
#define __Exception__
#include <iostream>
#include <sstream>
#include <string>
namespace Lib {
class ThrowableBase
{
};
template<class... Ms>
struct OutputAll;
template<class M, class... Ms>
struct OutputAll<M,Ms...> {
static void apply(std::ostream& out, M m, Ms... ms) {
out << m;
OutputAll<Ms...>::apply(out, ms...);
}
};
template<>
struct OutputAll<> {
static void apply(std::ostream& out) { }
};
class Exception : public ThrowableBase
{
template<class... Msg>
std::string toString(Msg... msg){
std::stringstream out;
OutputAll<Msg...>::apply(out, msg...);
return out.str();
}
public:
explicit Exception (const char* msg) : _message(msg) {}
Exception (const char* msg, int line);
explicit Exception (const std::string msg) : _message(msg) {}
template<class... Msg>
explicit Exception(Msg... msg)
: Exception(toString(msg...))
{ }
virtual void cry (std::ostream&) const;
virtual ~Exception() {}
const std::string& msg() { return _message; }
protected:
Exception () {}
std::string _message;
friend std::ostream& operator<<(std::ostream& out, Exception const& self)
{ self.cry(out); return out; }
};
class ParsingRelatedException : public Exception { using Exception::Exception; };
class UserErrorException
: public ParsingRelatedException
{
public:
using ParsingRelatedException::ParsingRelatedException;
unsigned line = 0;
std::string filename;
void cry (std::ostream&) const override;
};
class ValueNotFoundException
: public Exception
{
public:
ValueNotFoundException ()
: Exception("")
{}
};
class TimeLimitExceededException
: public Exception
{
public:
TimeLimitExceededException ()
: Exception("The time limit exceeded")
{}
};
class ActivationLimitExceededException
: public Exception
{
public:
ActivationLimitExceededException ()
: Exception("The activation limit exceeded")
{}
};
class InvalidOperationException
: public Exception
{
public:
InvalidOperationException (const char* msg)
: Exception(msg)
{}
InvalidOperationException (const std::string msg)
: Exception(msg)
{}
void cry (std::ostream&) const override;
};
class SystemFailException
: public Exception
{
public:
SystemFailException (const std::string msg, int err);
void cry (std::ostream&) const override;
int err;
};
class NotImplementedException
: public Exception
{
public:
NotImplementedException (const char* file,int line)
: Exception(""), file(file), line(line)
{}
void cry (std::ostream&) const override;
private:
const char* file;
int line;
};
}
#define VAMPIRE_EXCEPTION \
throw Lib::Exception(__FILE__,__LINE__)
#define USER_ERROR(...) \
throw Lib::UserErrorException(__VA_ARGS__)
#define INVALID_OPERATION(msg) \
throw Lib::InvalidOperationException(msg)
#define SYSTEM_FAIL(msg,err) \
throw Lib::SystemFailException(msg,err)
#define NOT_IMPLEMENTED \
throw Lib::NotImplementedException(__FILE__, __LINE__)
#endif