// Struct or union component list class -*- c++ -*-

#ifndef COMPONENTLIST_H_
# define COMPONENTLIST_H_
# ifdef __GNUC__
#  pragma interface
# endif // __GNUC__

# include <assert.h>
# include "Type.h"

/** @file ComponentList.h
 * List of struct or union components
 */

/* Copyright © 1998-2003 Marko Mäkelä (msmakela@tcs.hut.fi).

   This file is part of MARIA, a reachability analyzer and model checker
   for high-level Petri nets.

   MARIA is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   MARIA is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   The GNU General Public License is often shipped with GNU software, and
   is generally kept in a file called COPYING or LICENSE.  If you do not
   have a copy of the license, write to the Free Software Foundation,
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */

/** Struct or union component list */
class ComponentList
{
public:
  /** Constructor */
  ComponentList ();
  /** Copy constructor */
  ComponentList (const class ComponentList& old);
private:
  /** Assignment operator */
  class ComponentList& operator= (const class ComponentList& old);
public:
  /** Destructor */
  ~ComponentList ();

  /** Determine the number of components in the list */
  card_t getSize () const { return mySize; }
  /** Determine whether all components are ordered types */
  bool isOrdered () const {
    for (card_t i =  mySize; i--; )
      if (!(*this)[i].isOrdered ())
	return false;
    return true;
  }

  /** Get a component by name
   * @param name	name of the component
   * @return		pointer to the component, or NULL if not found
   */
  const class Type* operator[] (const char* name) const;

  /** Get a component by index number
   * @param i		index to the component
   * @return		reference to the component
   */
  const class Type& operator[] (card_t i) const {
    assert (i < getSize ());
    return *myTypes[i];
  }

  /** Get the index number of a component
   * @param name	name of the component
   * @return		index of the component
   */
  card_t getIndex (const char* name) const;

  /** Get the name of a component
   * @param i		index of the component
   */
  const char* getName (card_t i) const {
    assert (i < getSize ());
    return myNames[i];
  }

  /** See if the component list is assignable to another component list
   * @param other	the list this list should be assignable to
   * @return		true if this list is assignable to the list
   */
  bool isAssignable (const class ComponentList& other) const;
  /** See if the component list is always assignable to another component list
   * @param other	the list this list should always be assignable to
   * @return		true if this list always is assignable to the list
   */
  bool isAlwaysAssignable (const class ComponentList& other) const;

  /** See if a component in the list is assignable to a type
   * @param type	the type this list should be assignable to
   * @return		true if this list is assignable to the type
   */
  bool isAssignable (const class Type& type) const;

  /** See if a component in the list is assignable from a type
   * @param type	the type this list should be assignable from
   * @return		true if a component is assignable from the type
   */
  bool isAssignableFrom (const class Type& type) const;
  /** See if a component in the list is always assignable from a type
   * @param type	the type the list should always be assignable from
   * @return		true if a component always is assignable from the type
   */
  bool isAlwaysAssignableFrom (const class Type& type) const;

  /** Add a component
   * @param name	name of the component
   * @param type	type of the component
   */
  void addComponent (char* name, const class Type& type);

  /** Display the component list
   * @param printer	the printer object
   */
  void display (const class Printer& printer) const;

private:
  /** Number of components in the list */
  card_t mySize;
  /** Component names */
  char** myNames;
  /** Component types */
  const class Type** myTypes;
};

#endif // COMPONENTLIST_H_
