/****************************************************************************/
/* Copyright (c) 2000 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : idl.cc                                                        */
/* Author   : Tom O'Reilly                                                  */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/07/2000                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#include <string.h>
#include "idl.h"


Comment::Comment(const char *text)
{
  //  _text = strdup(text);

  // Will need to allocate memory for string, plus 1 for null terminator
  int nbytes = strlen(text) + 1;

  bool addNewline = false;

  if (text[strlen(text)-1] != '\n') {
    // Need additional byte for a newline
    nbytes++;
    addNewline = true;
  }

  _text = (char *)malloc(nbytes);
  strcpy(_text, text);
  if (addNewline)
    strcat(_text, "\n");
}


Comment::~Comment()
{
  free((void *)_text);
}


const char *Comment::text()
{
  return _text;
}


Base::Base(const char *name, Context *c)
{
  _name = strdup(name);
  context = c;
}


Base::~Base()
{
  free((void *)_name);
}


const char *Base::name()
{
  return _name;
}


DataInstance::DataInstance(const char *name, DataDefinition *dataDef,
			   Context *context)
  : Base(name, context)
{
  dataDefinition = dataDef;
}


DataInstance::~DataInstance()
{
}


DataDefinition::DataDefinition(const char *name, DataType dataType,
			       Context *context)
  : Base(name, context)
{
  _dataType = dataType;
}


DataDefinition::~DataDefinition()
{
}


DataType DataDefinition::dataType()
{
  return _dataType;
}


Interface *DataDefinition::definingInterface()
{
  Interface *definingInterface;

  Context *ctxt = context;
  bool found = false;
  while (ctxt) {

    if (ctxt->dataType() == InterfaceType)
      return (Interface *)ctxt;

    ctxt = ctxt->context;
  }

  // No defining interface? Should never get here!
  return 0;
}


Primitive::Primitive(DataType dataType, Context *context)
  : DataDefinition("primitive", dataType, context)
{
  
}


Primitive::~Primitive()
{
}


Context::Context(const char *name, DataType dataType, Context *context,
		 Context *parent)
  : DataDefinition(name, dataType, context)
{
  parentClass = parent;
}


Context::~Context()
{
}


Sequence::Sequence(const char *name, 
		   DataDefinition *elementDefinition, 
		   int maxElements, 
		   Context *context)
  : DataDefinition(name, SequenceType, context)
{
  element = elementDefinition;
  _maxElements = maxElements;
}


Sequence::~Sequence()
{
}


int Sequence::maxElements()
{
  return _maxElements;
}


Structure::Structure(const char *name, Context *context, 
		     Structure *parentClass)
  : Context(name, StructureType, context, parentClass)
{
}


Structure::~Structure()
{
}


Method::Method(const char *name, DataDefinition *returnDefinition, 
	       unsigned overloadCount)
  : Base(name)
{
  returnObject = returnDefinition;

  _overloadCount = overloadCount;
}


Method::~Method()
{
}


unsigned Method::overloadCount()
{
  return _overloadCount;
}



void Method::addArgument(const char *name, DataDefinition *dataDefinition,
			 IoSpecifier io)
{
  Method::Argument *arg = new Method::Argument(name, dataDefinition, io,
					       this->context);
  arguments.add(&arg);
}


Method::Argument::Argument(const char *name, DataDefinition *dataDefinition, 
			   IoSpecifier io, Context *context)
  : DataInstance(name, dataDefinition, context) 
{
  _io = io;
}


Method::Argument::~Argument()
{
}


Method::IoSpecifier Method::Argument::io()
{
  return _io;
}

			   
Interface::Interface(const char *name, Context *context, 
		     Interface *parentClass)
  : Context(name, InterfaceType, context, parentClass)
{
}


Interface::~Interface()
{
}


Enumeration::Enumeration(const char *name, Context *context)
  : DataDefinition(name, EnumerationType, context)
{
}


Enumeration::~Enumeration()
{
}


void Enumeration::addValue(const char *vname, bool defaultValue, int value)
{
  Enumeration::Value *thisValue = 
    new Enumeration::Value(vname, this->context, defaultValue, value);

  values.add(&thisValue);
}


Enumeration::Value::Value(const char *name, Context *context,
			  bool defaultValue, int value)
  : DataDefinition(name, LongType, context)
{
  _defaultValue = defaultValue;
  _value = value;
}


Enumeration::Value::~Value()
{
}


bool Enumeration::Value::defaultValue()
{
  return _defaultValue;
}


int Enumeration::Value::value()
{
  return _value;
}


bool primitiveType(DataType dataType)
{
  bool returnVal;

  switch (dataType) {
  case StructureType:
  case EnumerationType:
  case SequenceType:
  case InterfaceType:
    returnVal = false;
    break;

  default:
    returnVal = true;
  }

  return returnVal;
}


bool aggregateType(DataType dataType)
{
  if (!primitiveType(dataType) && dataType != EnumerationType)
    return true;
  else
    return false;
}
