#ifndef _gnException_h_
#define _gnException_h_

#include "gnClone.h"
#include "gn/gnExceptionCode.h"
#include <string>
#include <iostream>
#include <list>

class GNDLLEXPORT gnException
{
public:
	gnException( const char* const srcFile,
				 const unsigned int srcLine,
				 const char* const function,
				 gnExceptionCode& code, 
				 const char* const message );

	friend std::ostream& operator<<(std::ostream& os, const gnException& gne); //write to source.
	gnExceptionCode& GetCode(){return m_code;}
	string GetMessage(){return m_message;}
	void AddCaller(	const char* const function );
protected:
	gnExceptionCode& m_code;
	string m_message;
	const char* const m_file;
	unsigned int m_line;
	list<string> function_trace;
};

inline
gnException::gnException(const char* const srcFile, const unsigned int srcLine, const char* const function, gnExceptionCode& code, const char* const message ) : 
m_code(code), m_message(message), m_file(srcFile), m_line(srcLine){
	AddCaller(function);
}


GNDLLEXPORT 
std::ostream& operator<<(std::ostream& os, const gnException& gne); //write to source.


#ifdef __GNDEBUG__
#define STACK_TRACE_START try{
#define STACK_TRACE_END \
}catch(gnException& e){\
	e.AddCaller(__PRETTY_FUNCTION__);\
	throw e;\
}
#else
#define STACK_TRACE_START
#define STACK_TRACE_END
#endif // ifdef __DEBUG__

#define Throw_gnEx(code) throw gnException(__FILE__, __LINE__, __PRETTY_FUNCTION__, code, "")
#define Throw_gnExMsg(code,msg) throw gnException(__FILE__, __LINE__, __PRETTY_FUNCTION__, code, msg)
#endif //_gnException_h_
