//------------------------------------------------------------------------
//  Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
//
//  This file is part of the ZBar Bar Code Reader.
//
//  The ZBar Bar Code Reader is free software; you can redistribute it
//  and/or modify it under the terms of the GNU Lesser Public License as
//  published by the Free Software Foundation; either version 2.1 of
//  the License, or (at your option) any later version.
//
//  The ZBar Bar Code Reader is distributed in the hope that it will be
//  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
//  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser Public License for more details.
//
//  You should have received a copy of the GNU Lesser Public License
//  along with the ZBar Bar Code Reader; if not, write to the Free
//  Software Foundation, Inc., 51 Franklin St, Fifth Floor,
//  Boston, MA  02110-1301  USA
//
//  http://sourceforge.net/projects/zbar
//------------------------------------------------------------------------
#ifndef _ZBAR_EXCEPTION_H_
#define _ZBAR_EXCEPTION_H_

/// @file
/// C++ Exception definitions

#ifndef _ZBAR_H_
#error "include zbar.h in your application, **not** zbar/Exception.h"
#endif

#include <cstddef>
#include <exception>
#include <new>

namespace zbar
{
/// base class for exceptions defined by this API.
class Exception : public std::exception
{
public:
    /// create exception from C library error
    Exception(const void *obj = NULL) : std::exception(), _obj(obj)
    {
    }

    ~Exception() throw()
    {
    }

    /// retrieve error message
    virtual const char *what() const throw()
    {
	if (!_obj)
	    return ("zbar library unspecified generic error");
	return (_zbar_error_string(_obj, 0));
    }

private:
    const void *_obj;
};

/// internal library error.
class InternalError : public Exception
{
public:
    /// create exception from C library error
    InternalError(const void *obj) : Exception(obj)
    {
    }
};

/// unsupported request.
class UnsupportedError : public Exception
{
public:
    /// create exception from C library error
    UnsupportedError(const void *obj) : Exception(obj)
    {
    }
};

/// invalid request.
class InvalidError : public Exception
{
public:
    /// create exception from C library error
    InvalidError(const void *obj) : Exception(obj)
    {
    }
};

/// failed system call.
class SystemError : public Exception
{
public:
    /// create exception from C library error
    SystemError(const void *obj) : Exception(obj)
    {
    }
};

/// locking error.
class LockingError : public Exception
{
public:
    /// create exception from C library error
    LockingError(const void *obj) : Exception(obj)
    {
    }
};

/// all resources busy.
class BusyError : public Exception
{
public:
    /// create exception from C library error
    BusyError(const void *obj) : Exception(obj)
    {
    }
};

/// X11 display error.
class XDisplayError : public Exception
{
public:
    /// create exception from C library error
    XDisplayError(const void *obj) : Exception(obj)
    {
    }
};

/// X11 protocol error.
class XProtoError : public Exception
{
public:
    /// create exception from C library error
    XProtoError(const void *obj) : Exception(obj)
    {
    }
};

/// output window is closed.
class ClosedError : public Exception
{
public:
    /// create exception from C library error
    ClosedError(const void *obj) : Exception(obj)
    {
    }
};

/// image format error
class FormatError : public Exception
{
    // FIXME needs c equivalent

    virtual const char *what() const throw()
    {
	// FIXME what format?
	return ("unsupported format");
    }
};

/// @internal

/// extract error information and create exception.
static inline std::exception throw_exception(const void *obj)
{
    switch (_zbar_get_error_code(obj)) {
    case ZBAR_ERR_NOMEM:
	throw std::bad_alloc();
    case ZBAR_ERR_INTERNAL:
	throw InternalError(obj);
    case ZBAR_ERR_UNSUPPORTED:
	throw UnsupportedError(obj);
    case ZBAR_ERR_INVALID:
	throw InvalidError(obj);
    case ZBAR_ERR_SYSTEM:
	throw SystemError(obj);
    case ZBAR_ERR_LOCKING:
	throw LockingError(obj);
    case ZBAR_ERR_BUSY:
	throw BusyError(obj);
    case ZBAR_ERR_XDISPLAY:
	throw XDisplayError(obj);
    case ZBAR_ERR_XPROTO:
	throw XProtoError(obj);
    case ZBAR_ERR_CLOSED:
	throw ClosedError(obj);
    default:
	throw Exception(obj);
    }
}

} // namespace zbar

#endif
