/*-----------------------------------------------------------------*/
/*! 
  \file scscpprocedureterminated.cxx
  \brief SCSCP message : procedure terminated.
   class SCSCP_procedureterminatedoptions, SCSCP_procedureterminated
  \author  M. Gastineau 
           Astronomie et Systemes Dynamiques, IMCCE, CNRS, Observatoire de Paris. 

   Copyright, 2008, 2009, 2012, M. Gastineau, IMCCE-CNRS
   email of the author : gastineau@imcce.fr
*/
/*-----------------------------------------------------------------*/

/*-----------------------------------------------------------------*/
/* License  of this file :
 This file is "dual-licensed", you have to choose one  of the two licenses 
 below to apply on this file.
 
    CeCILL-C
    	The CeCILL-C license is close to the GNU LGPL.
    	( http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html )
 
 or CeCILL v2.0
      The CeCILL license is compatible with the GNU GPL.
      ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
 

This library is governed by the CeCILL-C or the CeCILL license under 
French law and abiding by the rules of distribution of free software.  
You can  use, modify and/ or redistribute the software under the terms 
of the CeCILL-C or CeCILL license as circulated by CEA, CNRS and INRIA  
at the following URL "http://www.cecill.info". 

As a counterpart to the access to the source code and  rights to copy,
modify and redistribute granted by the license, users are provided only
with a limited warranty  and the software's author,  the holder of the
economic rights,  and the successive licensors  have only  limited
liability. 

In this respect, the user's attention is drawn to the risks associated
with loading,  using,  modifying and/or developing or reproducing the
software by the user in light of its specific status of free software,
that may mean  that it is complicated to manipulate,  and  that  also
therefore means  that it is reserved for developers  and  experienced
professionals having in-depth computer knowledge. Users are therefore
encouraged to load and test the software's suitability as regards their
requirements in conditions enabling the security of their systems and/or 
data to be ensured and,  more generally, to use and operate it in the 
same conditions as regards security. 

The fact that you are presently reading this means that you have had
knowledge of the CeCILL-C or CeCILL license and that you accept its terms.
*/
/*-----------------------------------------------------------------*/


#if HAVE_CONFIG_H
#include "scscpconfig.h"
#endif /*HAVE_CONFIG_H*/
#include <stdio.h>
#if HAVE_STRING_H
#include <string.h>
#endif
#define __SCSCP_WITHIN_SCSCP
#include "scscp.h"
#include "scscpinternal.h"
#include "scscpdebug.h"
#include "scscptags.h"
#include "scscpfileclient.h"
#include "scscpfileserver.h"
#include "scscpprocedureterminated.h"

/*-----------------------------------------------------------------*/
/*  inlined  functions */
/*-----------------------------------------------------------------*/
/*! return the cd  */
static const char* SCSCP_procedureterminated_getcd(const SCSCP_procedureterminated* procterm) { return procterm->m_cdname; }
/*! return the symbol  */
static const char* SCSCP_procedureterminated_getsymbol(const SCSCP_procedureterminated* procterm) { return procterm->m_symbolname; }


/*-----------------------------------------------------------------*/
/*! constructor
   @param procterm (inout) procedure terminated
   @param options (inout) options of the procedure completed
   @param errormsg (inout) error message (not duplicated)
   @param symbolname (in) name of the symbol
   @param cdname (in) name of the CD
   @param status (inout) error code
*/
/*-----------------------------------------------------------------*/
int SCSCP_procedureterminated_init(SCSCP_procedureterminated* procterm, 
                             SCSCP_procedureterminatedoptions* options,
                             const_SCSCP_string cdname,
                             const_SCSCP_string symbolname, 
                             SCSCP_string errormsg,
                             SCSCP_status *status)
{
 procterm->m_ProcedureOptions = options;
 procterm->m_errormsg = errormsg;
 procterm->m_symbolname = symbolname;
 procterm->m_cdname = cdname;
 procterm->m_consterrormsg  = NULL;
 return 1;
}

/*-----------------------------------------------------------------*/
/*! constructor
   @param procterm (inout) procedure terminated
   @param options (inout) options of the procedure completed
   @param errormsg (in) error message
   @param symbolname (in) name of the symbol
   @param cdname (in) name of the CD
   @param status (inout) error code
*/
/*-----------------------------------------------------------------*/
int SCSCP_procedureterminated_init2(SCSCP_procedureterminated* procterm, 
                             SCSCP_procedureterminatedoptions* options,
                             const_SCSCP_string cdname,
                             const_SCSCP_string symbolname, 
                             const_SCSCP_string errormsg,
                             SCSCP_status *status)
{
 procterm->m_ProcedureOptions = options;
 procterm->m_errormsg = NULL;
 procterm->m_symbolname = symbolname;
 procterm->m_cdname = cdname;
 procterm->m_consterrormsg  = errormsg;
 return 1;
}

/*-----------------------------------------------------------------*/
/*! destructor
   @param procterm (inout) procedure terminated
   @param status (inout) error code
*/
/*-----------------------------------------------------------------*/
int SCSCP_procedureterminated_clear(SCSCP_procedureterminated* procterm, SCSCP_status *status)
{
 if (procterm->m_errormsg) free(procterm->m_errormsg);
 return 1;
}


/*-----------------------------------------------------------------*/
/*! return the error message
   @param procterm (inout) procedure terminated
   @param status (inout) error code
*/
/*-----------------------------------------------------------------*/
const char* SCSCP_procedureterminated_getmessage(const SCSCP_procedureterminated* procterm) 
{ 
 return procterm->m_errormsg!=NULL?procterm->m_errormsg:procterm->m_consterrormsg; 
}


/*-----------------------------------------------------------------*/
/*! write the object to the stream
   @param stream (inout) output stream
   @param status (inout) error code
   @param procterm (in) procedure terminated code
*/
/*-----------------------------------------------------------------*/
int SCSCP_procedureterminated_write(SCSCP_io *stream, const SCSCP_procedureterminated* procterm, SCSCP_status *status)
{
 int res;
 
 SCSCP_debugprint("SCSCP_procedureterminated_write(%p,%p,%p) - enter\n", stream, procterm, status);
 
 res = SCSCP_io_writeSCSCPSTART(stream, status);
 res &= SCSCP_io_writebeginOMOBJ(stream, status);
 	res &= SCSCP_io_writebeginOMATTR(stream, NULL, status);

   		//write the options
 		res &= SCSCP_ro_write(stream, procterm->m_ProcedureOptions, status);
  
 		res &= SCSCP_io_writebeginOMA(stream, NULL, status);
 
            //write procedure name
 			res &= SCSCP_io_writeOMS(stream, SCSCP_TAGS_cdname, SCSCP_TAGS_procedure_terminated, NULL, status);
 
 			res &= SCSCP_io_writeOMEwithOMSOMSTR(stream, 
 			                          procterm->m_cdname!=NULL?procterm->m_cdname:SCSCP_TAGS_cdname, 
                                      procterm->m_symbolname, 
                                      SCSCP_procedureterminated_getmessage(procterm),
                                      status);

 		res &= SCSCP_io_writeendOMA(stream, status); 
 	res &= SCSCP_io_writeendOMATTR(stream, status);
 res &= SCSCP_io_writeendOMOBJ(stream, status);
 res &= SCSCP_io_writeSCSCPEND(stream, status);
 
 SCSCP_debugprint("SCSCP_procedureterminated_write(,%d) - returns %d\n", SCSCP_status_is(status), res);
 return res;
}

/*-----------------------------------------------------------------*/
/*! read the object from the stream
   @param client (inout) scscp client
   @param node (in) current valid node. mustn't be NULL 
   @param procterm (inout) procedure terminated
   @param status (inout) status error
*/
/*-----------------------------------------------------------------*/
int SCSCP_procedureterminated_read(SCSCP_socketclient* client, SCSCP_xmlnodeptr* curnode, 
                                   SCSCP_procedureterminated* procterm, SCSCP_status *status)
{
 int res;
 SCSCP_debugprint("SCSCP_procedureterminated_read(%p, %p) - enter\n", curnode, procterm);
 
 res = SCSCP_sc_xmlnodereadOMEstr(client, curnode, &procterm->m_cdname, &procterm->m_symbolname, &procterm->m_errormsg, status);
   
 SCSCP_debugprint("SCSCP_procedureterminated_read(,%d) - returns %d\n", SCSCP_status_is(status), res);
 return res;
}


/*-----------------------------------------------------------------*/
/*! read the content of a "procedure terminated message" 
    and the error message is stored in  errortype and messagebuffer 
 @param client (inout) scscp client
 @param cdname (out) name of the cd for the error
                 This buffer must be freed with 'free'
 @param symbolname (out) name of the symbole for the error
                 This buffer must be freed with 'free'
 @param messagebuffer (out) openmath buffer. 
                 This buffer must be freed with 'free'
 @param status (inout) status error
*/
/*-----------------------------------------------------------------*/
int SCSCP_sc_callrecvterminated(SCSCP_socketclient* client, 
                                char **cdname, char **symbolname, 
                                char **messagebuffer, SCSCP_status* status)
{
 int res = SCSCP_sc_checkNULL(client, status);
 SCSCP_debugprint("SCSCP_procedureterminated_read(%p, %p, %p, %p, %p) - enter\n", client, cdname, symbolname, messagebuffer, status);
 if (res)
 {
  SCSCP_procedureterminatedoptions options;
  SCSCP_procedureterminated localterm;
  SCSCP_xmlnodeptr node;
  
  res = SCSCP_procedureterminated_init(&localterm, &options, NULL, NULL, NULL, status);
  node = SCSCP_sc_getxmlnode(client, status);
  res &= (node!=NULL);
  res &= SCSCP_procedureterminated_read(client, &node, &localterm, status);
  if (res)
  {
   const char *msgbuf = SCSCP_procedureterminated_getmessage(&localterm);
   *messagebuffer = SCSCP_strdup(msgbuf==NULL?"":msgbuf, status);
   *cdname = SCSCP_strdup(SCSCP_procedureterminated_getcd(&localterm), status);
   *symbolname = SCSCP_strdup(SCSCP_procedureterminated_getsymbol(&localterm), status);
   res = (*cdname && *symbolname && *messagebuffer);
  }
  SCSCP_procedureterminated_clear(&localterm, status);
 }
 SCSCP_debugprint("SCSCP_procedureterminated_read(%s,%s,%s,%d) - returns %d\n", *cdname, *symbolname, *messagebuffer, SCSCP_status_is(status), res);
 return res;
}

