#ifndef TDE_EXCEPTIONS_H
#define TDE_EXCEPTIONS_H

#include "config.h"

#include <cstdlib>

#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <memory.h>

namespace TDE {

class DataStoreException : public std::exception
{
private:
	std::string m_message;
public:
	DataStoreException() throw() : std::exception(), m_message("") {}
	DataStoreException(const std::string& message) throw() :
		std::exception(), m_message(message) {}
	DataStoreException(const DataStoreException& other) throw() :
		std::exception(), m_message(other.what()) {}
	virtual ~DataStoreException() throw() {}

	virtual const char* what() const throw() {
        return m_message.c_str();
    }
};

#define DEFINE_EXC_CLASS(NAME)								\
class NAME : public DataStoreException						\
{															\
public:														\
	NAME() throw() : DataStoreException() {}				\
	NAME(const std::string& message) throw() :				\
		DataStoreException(message) {}						\
	NAME(const DataStoreException& other) throw() :			\
		DataStoreException(other) {}						\
	NAME(const NAME& other) throw() :						\
		DataStoreException(other) {}						\
	virtual ~NAME() throw() {}								\
};

#define THROW_DFL( TEXT )						\
do {											\
	std::ostringstream _err_msg;				\
	_err_msg << TEXT;							\
	throw DataStoreException( _err_msg.str() );	\
} while(0)

#define THROW( EXC, TEXT )						\
do {											\
	std::ostringstream _err_msg;				\
	_err_msg << TEXT;							\
	throw (EXC)( _err_msg.str() );				\
} while(0)


DEFINE_EXC_CLASS(BackingStoreException);
DEFINE_EXC_CLASS(BackingStoreAlreadyOpened);
DEFINE_EXC_CLASS(BackingStoreNotAccessible);
DEFINE_EXC_CLASS(BackingStorePerms);
DEFINE_EXC_CLASS(BackingStoreWrongSize);
DEFINE_EXC_CLASS(BackingStore);

} /* end of namespace TDE */

#endif /* TDE_EXCEPTIONS_H */
