/*
 * SPDX-FileCopyrightText: 2004 Copyright contributors to the cppTango project
 *
 * SPDX-License-Identifier: LGPL-3.0-or-later
 */

#ifndef TANGO_SERVER_EXCEPT_H
#define TANGO_SERVER_EXCEPT_H

#include <tango/common/tango_const.h>
#include <tango/server/tango_current_function.h>

#include <ostream>
#include <string>
#include <vector>

namespace Tango
{

class DeviceImpl;

/*
 * Output operator overload for Tango::DevFailed
 */
static inline std::ostream &operator<<(std::ostream &ss, const Tango::DevFailed &devFailed)
{
    for(CORBA::ULong i = 0; i < devFailed.errors.length(); ++i)
    {
        const DevError &error = devFailed.errors[i];
        ss << "\tOrigin: " << error.origin << std::endl;
        ss << "\tSeverity: " << error.severity << std::endl;
        ss << "\tReason: " << error.reason << std::endl;
        ss << "\tDescription: " << error.desc << std::endl;
    }
    return ss;
}

//==================================================================================================================
//
// Class :
//        Except
//
// description :
//        This class is a container for all exceptions related methods to be used in aa Tango device server/client.
//        Most of these methods are static.
//
//==================================================================================================================

#define NOSPACEINDOC_EXCEPT

/**
 * Container class for all exception related methods. Most of these methods are
 * static methods
 *
 *
 *
 *
 * @headerfile tango.h
 * @ingroup Server
 * @ingroup Client
 */

class Except
{
  public:
    /**@name Exception related method */
    //@{
    /**
     * Print a TANGO exception.
     *
     * Print all the details of a TANGO exception.
     *
     * @param ex The exception object reference
     */
    static void print_exception(const CORBA::Exception &ex);

    //@}
    /**@name Exception related method */
    //@{
    /**
     * Print a TANGO exception.
     *
     * Print all the details of a TANGO exception to os.
     *
     * @param ex The exception object reference
     */
    static void print_exception(const CORBA::Exception &ex, std::ostream &os);
    //@}

    /**@name Error stack related method */
    //@{
    /**
     * Print a TANGO error stack.
     *
     * Print all the details of a TANGO error stack.
     *
     * @param ex The error stack reference
     */
    static void print_error_stack(const Tango::DevErrorList &ex);

    /**@name Error stack related method */
    //@{
    /**
     * Print a TANGO error stack.
     *
     * Print all the details of a TANGO error stack to os.
     *
     * @param ex The error stack reference
     */
    static void print_error_stack(const Tango::DevErrorList &ex, std::ostream &os);

    //@}

    /**@name Throw exception inline methods (static) */
    //@{
    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */
    [[noreturn]] static void
        throw_exception(const char *reason, const char *desc, const char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].desc = Tango::string_dup(desc);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason);
        errors[0].origin = Tango::string_dup(origin);

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * The memory used by the origin parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void
        throw_exception(const char *reason, const char *desc, char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].desc = Tango::string_dup(desc);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason);
        errors[0].origin = Tango::string_dup(origin);
        delete[] origin;

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * The memory used by the desc parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void
        throw_exception(const char *reason, char *desc, const char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].desc = Tango::string_dup(desc);
        delete[] desc;
        errors[0].origin = Tango::string_dup(origin);
        errors[0].reason = Tango::string_dup(reason);

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * The memory used by the origin and desc parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */
    [[noreturn]] static void
        throw_exception(const char *reason, char *desc, char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason);
        errors[0].origin = Tango::string_dup(origin);
        delete[] origin;
        errors[0].desc = Tango::string_dup(desc);
        delete[] desc;

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * The memory used by the reason parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void
        throw_exception(char *reason, const char *desc, const char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason);
        delete[] reason;
        errors[0].origin = Tango::string_dup(origin);
        errors[0].desc = Tango::string_dup(desc);

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * The memory used by the reason and origin parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void
        throw_exception(char *reason, const char *desc, char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason);
        delete[] reason;
        errors[0].origin = Tango::string_dup(origin);
        delete[] origin;
        errors[0].desc = Tango::string_dup(desc);

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * The memory used by the reason and desc parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void
        throw_exception(char *reason, char *desc, const char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason);
        delete[] reason;
        errors[0].origin = Tango::string_dup(origin);
        errors[0].desc = Tango::string_dup(desc);
        delete[] desc;

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * The memory used by the origin, reason and desc parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void
        throw_exception(char *reason, char *desc, char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason);
        delete[] reason;
        errors[0].origin = Tango::string_dup(origin);
        delete[] origin;
        errors[0].desc = Tango::string_dup(desc);
        delete[] desc;

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void throw_exception(const std::string &reason,
                                             const std::string &desc,
                                             const std::string &origin,
                                             Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason.c_str());
        errors[0].origin = Tango::string_dup(origin.c_str());
        errors[0].desc = Tango::string_dup(desc.c_str());

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void throw_exception(const std::string &reason,
                                             const std::string &desc,
                                             const char *origin,
                                             Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason.c_str());
        errors[0].origin = Tango::string_dup(origin);
        errors[0].desc = Tango::string_dup(desc.c_str());

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void throw_exception(const std::string &reason,
                                             const char *desc,
                                             const std::string &origin,
                                             Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason.c_str());
        errors[0].origin = Tango::string_dup(origin.c_str());
        errors[0].desc = Tango::string_dup(desc);

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void throw_exception(const std::string &reason,
                                             const char *desc,
                                             const char *origin,
                                             Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason.c_str());
        errors[0].origin = Tango::string_dup(origin);
        errors[0].desc = Tango::string_dup(desc);

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void throw_exception(const char *reason,
                                             const std::string &desc,
                                             const std::string &origin,
                                             Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason);
        errors[0].origin = Tango::string_dup(origin.c_str());
        errors[0].desc = Tango::string_dup(desc.c_str());

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void throw_exception(const char *reason,
                                             const std::string &desc,
                                             const char *origin,
                                             Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason);
        errors[0].origin = Tango::string_dup(origin);
        errors[0].desc = Tango::string_dup(desc.c_str());

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void throw_exception(const char *reason,
                                             const char *desc,
                                             const std::string &origin,
                                             Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason);
        errors[0].origin = Tango::string_dup(origin.c_str());
        errors[0].desc = Tango::string_dup(desc);

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * The memory used by the origin parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void throw_exception(const std::string &reason,
                                             const std::string &desc,
                                             char *origin,
                                             Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason.c_str());
        errors[0].origin = Tango::string_dup(origin);
        delete[] origin;
        errors[0].desc = Tango::string_dup(desc.c_str());

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * The memory used by the desc parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void throw_exception(const std::string &reason,
                                             char *desc,
                                             const std::string &origin,
                                             Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason.c_str());
        errors[0].origin = Tango::string_dup(origin);
        errors[0].desc = Tango::string_dup(desc);
        delete[] desc;
        errors[0].desc = Tango::string_dup(origin.c_str());

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * The memory used by the origin and desc parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void
        throw_exception(const std::string &reason, char *desc, char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason.c_str());
        errors[0].origin = Tango::string_dup(origin);
        delete[] origin;
        errors[0].desc = Tango::string_dup(desc);
        delete desc;

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * The memory used by the reason parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void throw_exception(char *reason,
                                             const std::string &desc,
                                             const std::string &origin,
                                             Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason);
        delete[] reason;
        errors[0].origin = Tango::string_dup(origin.c_str());
        errors[0].desc = Tango::string_dup(desc.c_str());

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * The memory used by the reason and origin parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void
        throw_exception(char *reason, const std::string &desc, char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason);
        delete[] reason;
        errors[0].origin = Tango::string_dup(origin);
        delete[] origin;
        errors[0].desc = Tango::string_dup(desc.c_str());

        throw Tango::DevFailed(errors);
    }

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A default value "Tango::ERR" is defined for the DevError
     * severity field.
     * The memory used by the reason and desc parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void
        throw_exception(char *reason, char *desc, const std::string &origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::DevErrorList errors(1);

        errors.length(1);
        errors[0].severity = sever;
        errors[0].reason = Tango::string_dup(reason);
        delete[] reason;
        errors[0].origin = Tango::string_dup(origin.c_str());
        errors[0].desc = Tango::string_dup(desc);
        delete[] desc;

        throw Tango::DevFailed(errors);
    }

    //@}

    /**@name Re-throw exception inline methods (static) */
    //@{
    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */
    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                const char *reason,
                                                const char *desc,
                                                const char *origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].desc = Tango::string_dup(desc);
        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason);
        ex.errors[nb_err].origin = Tango::string_dup(origin);

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * The memory used by the origin parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(
        Tango::DevFailed &ex, const char *reason, const char *desc, char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].desc = Tango::string_dup(desc);
        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason);
        ex.errors[nb_err].origin = Tango::string_dup(origin);
        delete[] origin;

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * The memory used by the desc parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(
        Tango::DevFailed &ex, const char *reason, char *desc, const char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].desc = Tango::string_dup(desc);
        delete[] desc;
        ex.errors[nb_err].origin = Tango::string_dup(origin);
        ex.errors[nb_err].reason = Tango::string_dup(reason);

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * The memory used by the origin and desc parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */
    [[noreturn]] static void re_throw_exception(
        Tango::DevFailed &ex, const char *reason, char *desc, char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason);
        ex.errors[nb_err].origin = Tango::string_dup(origin);
        delete[] origin;
        ex.errors[nb_err].desc = Tango::string_dup(desc);
        delete[] desc;

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * The memory used by the reason parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(
        Tango::DevFailed &ex, char *reason, const char *desc, const char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason);
        delete[] reason;
        ex.errors[nb_err].origin = Tango::string_dup(origin);
        ex.errors[nb_err].desc = Tango::string_dup(desc);

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * The memory used by the reason and origin parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(
        Tango::DevFailed &ex, char *reason, const char *desc, char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason);
        delete[] reason;
        ex.errors[nb_err].origin = Tango::string_dup(origin);
        delete[] origin;
        ex.errors[nb_err].desc = Tango::string_dup(desc);

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * The memory used by the reason and desc parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(
        Tango::DevFailed &ex, char *reason, char *desc, const char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason);
        delete[] reason;
        ex.errors[nb_err].origin = Tango::string_dup(origin);
        ex.errors[nb_err].desc = Tango::string_dup(desc);
        delete[] desc;

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * The memory used by the origin, reason and desc parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(
        Tango::DevFailed &ex, char *reason, char *desc, char *origin, Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason);
        delete[] reason;
        ex.errors[nb_err].origin = Tango::string_dup(origin);
        delete[] origin;
        ex.errors[nb_err].desc = Tango::string_dup(desc);
        delete[] desc;

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                const std::string &reason,
                                                const std::string &desc,
                                                const std::string &origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason.c_str());
        ex.errors[nb_err].origin = Tango::string_dup(origin.c_str());
        ex.errors[nb_err].desc = Tango::string_dup(desc.c_str());

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                const std::string &reason,
                                                const std::string &desc,
                                                const char *origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason.c_str());
        ex.errors[nb_err].origin = Tango::string_dup(origin);
        ex.errors[nb_err].desc = Tango::string_dup(desc.c_str());

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                const std::string &reason,
                                                const char *desc,
                                                const std::string &origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason.c_str());
        ex.errors[nb_err].origin = Tango::string_dup(origin.c_str());
        ex.errors[nb_err].desc = Tango::string_dup(desc);

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                const std::string &reason,
                                                const char *desc,
                                                const char *origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason.c_str());
        ex.errors[nb_err].origin = Tango::string_dup(origin);
        ex.errors[nb_err].desc = Tango::string_dup(desc);

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                const char *reason,
                                                const std::string &desc,
                                                const std::string &origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason);
        ex.errors[nb_err].origin = Tango::string_dup(origin.c_str());
        ex.errors[nb_err].desc = Tango::string_dup(desc.c_str());

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                const char *reason,
                                                const std::string &desc,
                                                const char *origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason);
        ex.errors[nb_err].origin = Tango::string_dup(origin);
        ex.errors[nb_err].desc = Tango::string_dup(desc.c_str());

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                const char *reason,
                                                const char *desc,
                                                const std::string &origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason);
        ex.errors[nb_err].origin = Tango::string_dup(origin.c_str());
        ex.errors[nb_err].desc = Tango::string_dup(desc);

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * The memory used by the origin parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                const std::string &reason,
                                                const std::string &desc,
                                                char *origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason.c_str());
        ex.errors[nb_err].origin = Tango::string_dup(origin);
        delete[] origin;
        ex.errors[nb_err].desc = Tango::string_dup(desc.c_str());

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * The memory used by the desc parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                const std::string &reason,
                                                char *desc,
                                                const std::string &origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason.c_str());
        ex.errors[nb_err].origin = Tango::string_dup(origin.c_str());
        ex.errors[nb_err].desc = Tango::string_dup(desc);
        delete[] desc;

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * The memory used by the origin and desc parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                const std::string &reason,
                                                char *desc,
                                                char *origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason.c_str());
        ex.errors[nb_err].origin = Tango::string_dup(origin);
        delete[] origin;
        ex.errors[nb_err].desc = Tango::string_dup(desc);
        delete desc;

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * The memory used by the reason parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                char *reason,
                                                const std::string &desc,
                                                const std::string &origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason);
        delete[] reason;
        ex.errors[nb_err].origin = Tango::string_dup(origin.c_str());
        ex.errors[nb_err].desc = Tango::string_dup(desc.c_str());

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * The memory used by the reason and origin parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                char *reason,
                                                const std::string &desc,
                                                char *origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason);
        delete[] reason;
        ex.errors[nb_err].origin = Tango::string_dup(origin);
        delete[] origin;
        ex.errors[nb_err].desc = Tango::string_dup(desc.c_str());

        throw ex;
    }

    /**
     * Re-throw a TANGO DevFailed exception with one more error.
     *
     * The exception is re-thrown with one more DevError
     * object. A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * The memory used by the reason and desc parameter will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex The DevFailed exception
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */

    [[noreturn]] static void re_throw_exception(Tango::DevFailed &ex,
                                                char *reason,
                                                char *desc,
                                                const std::string &origin,
                                                Tango::ErrSeverity sever = Tango::ERR)
    {
        long nb_err = ex.errors.length();
        ex.errors.length(nb_err + 1);

        ex.errors[nb_err].severity = sever;
        ex.errors[nb_err].reason = Tango::string_dup(reason);
        delete[] reason;
        ex.errors[nb_err].origin = Tango::string_dup(origin.c_str());
        ex.errors[nb_err].desc = Tango::string_dup(desc);
        delete[] desc;

        throw ex;
    }

    //@}

    /**@name Other throw exception methods */
    //@{
    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A value "Tango::ERR" is defined for the DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex A CORBA System Exception. The reason and desc fields of the
     * DevError object will be set according to the data in this exception.
     * The desc field is always set to API_CorbaSysException and the reason flag is
     * different depending on the exact type of the CORBA system exception.
     * @param origin The exception DevError object origin field
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */
    [[noreturn]] static void throw_exception(const CORBA::SystemException &ex, const char *origin);

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A value "Tango::ERR" is defined for the DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex A CORBA System Exception. The reason and desc fields of the
     * DevError object will be set according to the data in this exception.
     * The desc field is always set to API_CorbaSysException and the reason flag is
     * different depending on the exact type of the CORBA system exception.
     * @param origin The exception DevError object origin field. The memory
     * allocated for this parameter will be freed by this method.
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */
    [[noreturn]] static void throw_exception(const CORBA::SystemException &ex, char *origin);

    /**
     * Generate and throw a TANGO DevFailed exception.
     *
     * The exception is created with a single DevError
     * object. A value "Tango::ERR" is defined for the DevError
     * severity field.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex A CORBA System Exception. The reason and desc fields of the
     * DevError object will be set according to the data in this exception.
     * The desc field is always set to API_CorbaSysException and the reason flag is
     * different depending on the exact type of the CORBA system exception.
     * @param origin The exception DevError object origin field. The memory
     * allocated for this parameter will be freed by this method.
     * @exception DevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     */
    [[noreturn]] static void throw_exception(const CORBA::SystemException &ex, const std::string &origin);

    /**
     * Throw a TANGO MultiDevFailed exception.
     *
     * Throw a MultiDevFailed exception with one more DevError
     * object for the attribute with name given as first parameter.
     * A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * Note that throwing MultiDevFailed exception is allowed only in attribute writing methods.
     * The memory used by the origin and desc parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param att_name The attribute name
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception MultiDevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>MultiDevFailed</b> exception specification
     */

    [[noreturn]] static void throw_named_exception(const char *att_name,
                                                   const char *reason,
                                                   const char *desc,
                                                   const char *origin,
                                                   Tango::ErrSeverity sever = Tango::ERR)
    {
        Tango::NamedDevErrorList errors(1);

        errors.length(1);
        errors[0].name = Tango::string_dup(att_name);
        errors[0].index_in_call = 999;
        errors[0].err_list.length(1);
        errors[0].err_list[0].desc = Tango::string_dup(desc);
        errors[0].err_list[0].severity = sever;
        errors[0].err_list[0].reason = Tango::string_dup(reason);
        errors[0].err_list[0].origin = Tango::string_dup(origin);

        throw Tango::MultiDevFailed(errors);
    }

    /**
     * Throw a TANGO MultiDevFailed exception.
     *
     * Throw a MultiDevFailed exception with one more DevError
     * object for the attribute list with names given as first parameter.
     * A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * Note that throwing MultiDevFailed exception is allowed only in attribute writing methods.
     * The memory used by the origin and desc parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param atts The attributes name vector
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception MultiDevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>MultiDevFailed</b> exception specification
     */
    [[noreturn]] static void throw_named_exception(std::vector<std::string> &atts,
                                                   const char *reason,
                                                   const char *desc,
                                                   const char *origin,
                                                   Tango::ErrSeverity sever = Tango::ERR)
    {
        unsigned int a_size = (unsigned int) atts.size();
        Tango::NamedDevErrorList errors(a_size);

        errors.length(a_size);
        for(unsigned int loop = 0; loop < a_size; loop++)
        {
            errors[loop].name = Tango::string_dup(atts[loop].c_str());
            errors[loop].index_in_call = 999;
            errors[loop].err_list.length(1);
            errors[loop].err_list[0].desc = Tango::string_dup(desc);
            errors[loop].err_list[0].severity = sever;
            errors[loop].err_list[0].reason = Tango::string_dup(reason);
            errors[loop].err_list[0].origin = Tango::string_dup(origin);
        }

        throw Tango::MultiDevFailed(errors);
    }

    /**
     * Throw a TANGO MultiDevFailed exception.
     *
     * Throw a MultiDevFailed exception with one more DevError
     * object for one attribute with index given as second parameter.
     * The attributes index is the index received by the write_attr_hardware() method.
     * A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * Note that throwing MultiDevFailed exception is allowed only in attribute writing methods.
     *
     * The memory used by the origin and desc parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param d The device pointer
     * @param att_idx The attributes index
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception MultiDevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>MultiDevFailed</b> exception specification
     */

    [[noreturn]] static void throw_named_exception(Tango::DeviceImpl *d,
                                                   long att_idx,
                                                   const char *reason,
                                                   const char *desc,
                                                   const char *origin,
                                                   Tango::ErrSeverity sever = Tango::ERR);

    /**
     * Throw a TANGO MultiDevFailed exception.
     *
     * Throw a MultiDevFailed exception with one more DevError
     * object for the attribute list with indexes given as second parameter.
     * The attributes indexes are the index received by the write_attr_hardware() method.
     * A default value "Tango::ERR" is defined for the new DevError
     * severity field.
     * Note that throwing MultiDevFailed exception is allowed only in attribute writing methods.
     *
     * The memory used by the origin and desc parameters will be freed by this method
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param d The device pointer
     * @param atts The attributes indexes vector
     * @param reason The exception DevError object reason field
     * @param desc The exception DevError object desc field
     * @param origin The exception DevError object origin field
     * @param sever The exception DevError object severity field
     * @exception MultiDevFailed The thrown exception.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>MultiDevFailed</b> exception specification
     */

    [[noreturn]] static void throw_named_exception(Tango::DeviceImpl *d,
                                                   std::vector<long> &atts,
                                                   const char *reason,
                                                   const char *desc,
                                                   const char *origin,
                                                   Tango::ErrSeverity sever = Tango::ERR);

    /**
     * Compare two Tango DevFailed exceptions for equality
     *
     * The two DevFailed exceptions are verified by comparing the
     * reason, origin, description and severity of all exceptions in the error stack.
     * The strings reason, origin and description are compared literally.
     * Click <a href="https://tango-controls.readthedocs.io/en/latest/development/advanced/IDL.html#exceptions">here</a>
     * to read <b>DevFailed</b> exception specification
     *
     * @param ex1 The first DevFailed exception
     * @param ex2 The second DevFailed exception
     * @return A boolean set to true if the two exceptions are equal
     */
    static bool compare_exception(Tango::DevFailed &ex1, Tango::DevFailed &ex2);

    //@}

    /// @privatesection

    static char *print_CORBA_SystemException(const CORBA::SystemException *);
    static char *print_CORBA_SystemException_r(const CORBA::SystemException *, char *err_msg); // reentrant version
    static omni_mutex the_mutex;

  protected:
    /// @privatesection
    static char mess[256];
};

// Note: This returns raw pointer to a temporary c-string, it must be copied (e.g. with string_dup).
#define TANGO_EXCEPTION_ORIGIN (std::string(TANGO_CURRENT_FUNCTION) + " at (" TANGO_FILE_AND_LINE ")").c_str()

#define TANGO_THROW_EXCEPTION(reason, desc) ::Tango::Except::throw_exception(reason, desc, TANGO_EXCEPTION_ORIGIN)

#define TANGO_RETHROW_EXCEPTION(original, reason, desc) \
    ::Tango::Except::re_throw_exception(original, reason, desc, TANGO_EXCEPTION_ORIGIN)

} // namespace Tango

#endif /* EXCEPT */
