
/**********************************************************//**
 **
 ** @file base/exception.h
 **
 ** Copyright (C) 2010  Xpace, LLC.  All rights reserved
 **
 ** www.xpace.net
 **
 **************************************************************/

#ifndef XPACE_EXCEPTION_H
#define XPACE_EXCEPTION_H

#include <exception>
#include <vector>

#include "base/types.h"

namespace Xpace 
{
  class exceptionImpl;

  class XPACE_EXPORT Exception : public std::exception
  {
  public:
    Exception
      ();
    Exception
      (const Exception&);
    Exception& operator=
      (const Exception&);
    virtual ~Exception
      () throw();

    /// @return true if empty
    bool operator!
      ()
      const;

    /// @return the exception that caused this one (if any)
	  const Exception why
      () 
      const;

    /// @return English template into which params will be inserted
	  const String getTemplate
      () 
      const;

    /// Construct an error message
    /// @param templ the template into which params will be inserted
    ///   (I.e., a translation of getTemplate() for this exception)
    ///   if = String(), use English template
    /// @return the translated template with params insterted
    String getMessage
      (const String& templ = String())   
      const;

    /// @return an English error message with params inserted
		const char* what() 
      const throw();

  protected:
    /// @param templ construct an Exception with this message template
    /// @param reason cause for this Exception, if any
    Exception
      (const String& templ,
       const Exception reason = Exception());

    /// Add a parameter to this exception
    /// The first parameter added will replace '%1' in the template, 
    /// the second will replace '%2', and so on.
    /// @param p the param to be added
    void addParam
      (const String& p);

  private:
    friend class exceptionImpl;
    exceptionImpl* impl;
    Exception
      (const exceptionImpl* i);
  };

  /// General exceptions

  class Unimplemented_Error : public Exception
  {
  public:
     /// @param desc a description
     Unimplemented_Error
       (const String& desc);
  };

  class Bounds_Error : public Exception
  {
  public:
    /// @param bad the bad vslue
    /// @param max the maximum it should be
    Bounds_Error
      (int64 bad,
       int64 max);
  };

  class Corrupt_Error : public Exception
  {
  public:
    /// @param desc what is corrupt
    /// @param pos where it is corrupt
    Corrupt_Error
      (String desc,
       int64 pos);
  };

  // ================================ ANY EXCEPTION ===========

  /// Never thrown, but a convenient holder for std and Xpace exceptions
  class AnyException : public Exception
  {
  public:
    AnyException
      ();
    explicit AnyException
      (const Xpace::Exception& ex);
    explicit AnyException
      (const std::exception& ex);

    /// @return true if empty
    bool operator!
      ()
      const;    

    const Xpace::String getTemplate
      () 
      const;

    String getMessage
      (const String& templ = String())   
      const;

    Exception why
      ();

    const char* what
      ()
      const throw();

    bool isBadAlloc
      ()
      const;

  private:
    const Exception xpace_ex;
    Exception cur_ex;
    const std::exception std_ex;
  };
}

#endif
