//
// Error class for PTC 2.0 C++ API
// Copyright (c) 1998 Glenn Fiedler (ptc@gaffer.org)
// This source code is licensed under the GNU LGPL
//

// include files
#include "Error.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>




Error::Error()
{
    // defaults
    defaults();
}


Error::Error(const char message[])
{
    // allocate new message
    m_message = new char[strlen(message)+1];

    // set error message
    strcpy(this->m_message,message);
}


Error::Error(const char message[],const Error &error)
{
    // calculate length of composite error message string
    int length = strlen(message) + strlen("\n") + strlen(error.m_message) + 1;

    // allocate new message
    m_message = new char[length];

    // setup composite error message
    sprintf(m_message,"%s\n%s",message,error.m_message);
}


Error::Error(const Error &error)
{
    // defaults
    defaults();

    // assignment
    *this = error;
}


Error::~Error()
{
    // free message
    delete[] m_message;
}




void Error::report() const
{
    //
    // Report error
    // ------------
    //
    // This function should report an error string to the user in
    // the most natural way on the target platform and exit the program.
    //
    // The implementation below just outputs an error string to stdout,
    // however, on many platforms there is a better way to report errors.
    // For example, under Win32 the best way is to just pop up an error
    // message box. Under unix reporting the error to stderr would
    // probably be more appropriate.
    //
    // It is up to the implementer to code the most appropriate error
    // reporting method for the target platform.
    //
    // Please note that when the composite constructor is called the 
    // error message becomes a composite of the new error message and
    // the old error message like so:
    //
    //     try
    //     {
    //         throw Error("some obscure internal error");
    //     }
    //     catch (Error &error)
    //     {
    //         throw Error("could not perform some high level operation",error);
    //     }
    //
    // This would result in the following error message string:
    //
    // "could not perform some high level operation\nsome obscure internal error"
    //
    // In other words, make sure your "Error::report" implementation can handle
    // error messages with multiple lines :)
    //

    // report error
    printf("error: %s\n",m_message);

    // exit
    exit(1);
}




const char* Error::message() const
{
    // get message
    return m_message;
}




Error& Error::operator =(const Error &error)
{
    // check for self assignment
    if (this==&error) throw Error("self assignment is not allowed");
        
    // check if error message string will fit in this one
    if (strlen(error.m_message)>strlen(m_message))
    {
        // free old message
        delete[] m_message;

        // allocate new message
        m_message = new char[strlen(error.m_message)];
    }

    // copy error message string
    strcpy(m_message,error.m_message);

    // finished
    return *this;
}


bool Error::operator ==(const Error &error) const
{
    // is equal to
    if (!strcmp(error.m_message,m_message)) return true;
    else return false;
}


bool Error::operator !=(const Error &error) const
{
    // not equal to
    return !(*this==error);
}




void Error::defaults()
{
    // defaults
    m_message = new char[1];
    m_message[0] = 0;
}
