/*****************************************************************************
 * File:  sys_mechs.c
 *
 *
 * Notice:
 *   (C) Copyright 1999, 2000 ROX Software, Inc.
 *   All rights reserved.
 *
 * Model Compiler:  MC3020 V1.3.0
 *
 * Warnings:
 *   !!! THIS IS AN AUTO-GENERATED FILE. PLEASE DO NOT EDIT. !!!
 ****************************************************************************/

#include <stdlib.h>

#include "sys_init.h"

#include "e_mechs.h"
#include "e_events.h"
#include "e_objset.h"

/*****************************************************************************
 ****************************************************************************/
static Escher_ObjectSet_s * node1_FreeList = (Escher_ObjectSet_s *) 0;
static Escher_ObjectSet_s node1s[ SYS_MAX_CONTAINERS ];

/*****************************************************************************
 * Initialize the node1 instances by linking them into a collection.
 * These containoids will be collected into a null-terminated,
 * singly linked list (slist).
 * This needs to be called during architecture initialization.
 ****************************************************************************/
void
Escher_SetFactoryInit()
{
  unsigned int i;
  node1_FreeList = &node1s[ 0 ];
  /* Build the collection (linked list) of node1 instances.  */
  for ( i = 0; i < ( SYS_MAX_CONTAINERS - 1 ); i++ )
  {
    node1s[ i ].next = &node1s[ i + 1 ];
    node1s[ i ].object = 0;
  }
  node1s[ SYS_MAX_CONTAINERS - 1 ].next = (Escher_ObjectSet_s *) 0;
}

/*****************************************************************************
 * Escher_CopySet
 ****************************************************************************/
void 
Escher_CopySet( Escher_ObjectSet_s * const to_set,
                Escher_ObjectSet_s * const from_set )
{
  Escher_ObjectSet_s * slot;

  /* May be copying into an existing set, release target collection nodes.  */
  Escher_ClearSet( to_set );
  Escher_InitSet( to_set );

  for ( slot = from_set->next; slot; slot = slot->next )
  {
    Escher_SetInsertElement( to_set, slot->object ); 
  }
}

/*****************************************************************************
 * Escher_ClearSet
 ****************************************************************************/
void
Escher_ClearSet( Escher_ObjectSet_s * const set )
{
  Escher_ObjectSet_s * slot, * new_slot;

  for ( slot = set->next; slot; )
  {
    new_slot = slot->next;
    Escher_SetRemoveElement( set, slot->object ); 
    slot = new_slot;
  }
  Escher_InitSet( set );
}

/*****************************************************************************
 * Escher_SetInsertElement
 ****************************************************************************/
void
Escher_SetInsertElement( Escher_ObjectSet_s * const set,
                         void * const element )
{
  Escher_ObjectSet_s * slot;

  if ( ! node1_FreeList )
  {
    UserNodeListEmptyCallout(); /* Bad news!  No more nodes.         */
  }
  else
  {
    slot = node1_FreeList;   /* Extract node from head of free list.  */
    node1_FreeList = node1_FreeList->next;
    slot->object = element;
    slot->next = set->next;  /* Insert element at front of list.  */
    set->next = slot;
  }
}

/*****************************************************************************
 * Escher_SetRemoveNode
 ****************************************************************************/
Escher_ObjectSet_s *
Escher_SetRemoveNode( Escher_ObjectSet_s * const set,
                      const void * const d )
{
  Escher_ObjectSet_s * t = set->next; /* Start with first node.      */
  /* Find node containing data and unlink from list.  */
  if ( t->object == d )         /* Element found at head.            */
  {
    set->next = t->next;        /* Unlink it from the list.          */
  }
  else
  {
    Escher_ObjectSet_s * t_old;
    do                          /* Search for data element.          */
    {
      t_old = t;
      t = t->next;
      if ( t == (Escher_ObjectSet_s *) 0 ) return 0; /* absent       */
    } while ( t->object != d );
    t_old->next = t->next;      /* Unlink element from the list.     */
  }
  return t;
}

/*****************************************************************************
 * Escher_SetRemoveElement
 ****************************************************************************/
void
Escher_SetRemoveElement( Escher_ObjectSet_s * const set,
                         const void * const d )
{
  Escher_ObjectSet_s * t;
  if ( ! set->next ) return;    /* empty set */
  t = Escher_SetRemoveNode( set, d );
  /* Return node to architecture collection (free list).             */
  if ( t )
  {
    t->next = node1_FreeList;
    node1_FreeList = t;
  }
}

/*****************************************************************************
 * Return true when the set contains the given data element.
 * Return false if not found.
 ****************************************************************************/
bool
Escher_SetContains( Escher_ObjectSet_s * const set,
                    const void * const element )
{
  Escher_ObjectSet_s * t = set;

  while ( ( t = t->next ) != 0 )
  {
    if ( t->object == element ) return true;  /* found  */
  }
  return false;                               /* absent */
}

/*****************************************************************************
 * Escher_SetCardinality
 ****************************************************************************/
int 
Escher_SetCardinality( const Escher_ObjectSet_s * const set )
{
  int result = 0;
  Escher_ObjectSet_s * node;

  for ( node = set->next; node; node = node->next )
  {
    result++;
  }

  return result;
}

/*****************************************************************************
 * Escher_SetEquality
 ****************************************************************************/
bool
Escher_SetEquality( Escher_ObjectSet_s * const left_set,
                    Escher_ObjectSet_s * const right_set )
{
  if ( !left_set || !right_set )
    return false;

  if ( Escher_SetCardinality( left_set ) != Escher_SetCardinality( right_set ) )
    return false;

  return true;
}

/*****************************************************************************
 * The iterator uses a cursor external to the set (or extent).
 * This cursor maintains a flavor of current element.
 ****************************************************************************/
void * 
Escher_IteratorNext( Escher_Iterator_s * const iter )
{
  if ( !iter->cursor )
  {
    return (void *) 0;
  }
  else
  {
    void * element;
    element = iter->cursor->object;
    iter->cursor = iter->cursor->next;
    return element;
  }
}