//============================================================
//     File:      containr.hpp
//     By:        Roger Z. Rios-Mercado
//     Date:      Fall 1993 (for EE360C)
//     Modified:  SP/94
//     Comment:   For the FUTMEX project, this file should NOT
//                be further modified.
//============================================================
//
//    This file defines the class <container>, which is intended 
// to be a base class for a wide variety of data structures like 
// linked lists, search trees, hash tables, etc.  The container 
// base class declares all the methods that the other classes 
// must provide and declares all these methods to be virtual.
// This sets up the polymorphism so the derived classes can all 
// be treated as the base class.
//
// Requirements:
//    o  Any class derived from container must implement all the 
//       methods defined in container.
//    o  The derived class constructor must be virtual.
//    o  The inheritance must be public (permits base class 
//       pointers).
//    o  The methods must follow the general behavior for insert, 
//       delete, find, print etc...
//============================================================

#ifndef CONTAINER_HPP
#define CONTAINER_HPP

#include <string.h>
#include <stdio.h>
#include <assert.h>

class conyainer;  //

class container {
public:
     container(int (*cmp)(void*, void*), char* s) : 
     compare(cmp), keycount(0) {
          name = new char [strlen(s) + 1];
          assert (name);
	  strcpy(name, s);
     }
     //virtual ~container() { delete [] name; }   [use in unix]
     virtual ~container() { delete name; }
     //
     //   True if structure contains no data. 
     virtual int isempty() { return (keycount == 0); }
     //
     //   Put an entity in the structure, copy only the data ptr.
     virtual int insert(void*) = 0;
     //
     //   Insert data entity at beginning of structure.
     virtual int insertfirst(void*) = 0;
     //
     //   Insert data entity at end of structure.
     virtual int insertlast(void*) = 0;
     //
     //   Print out the data in the structure.
     virtual void print() = 0;
     //
     //   Empty, but don't delete structure.
     virtual void flush() = 0;
     //
     //   Empty,, but don't delete data entities.
     virtual void flush_nodes() = 0;
     //
     //   Remove data entity from structure, return data ptr.
     virtual void* remove(void*) = 0;
     //
     //   Find data entity in structure, do not remove, return
     //   data ptr.
     virtual void* find(void*) = 0;
     //
     //   Return ptr to first data entity in the structure.
     virtual void* first() = 0;
     //
     //   Return ptr to last data entity in the structure.
     virtual void* last() = 0;
     //
     //   Return ptr to next data entity, affected by access. 
     virtual void* next() = 0;
     //
     //   Return ptr to previous data entity, affected by access.
     virtual void* prev() = 0;
     //
     //   Traverse the structure and apply opfn() to each data entity.
     void  traverse_op(void (*opfn)(void*));
     void traverse_op(FILE*, void (*opfn)(FILE*, void*));
     //
     //   Per instance identity of structure, helps in debugging.
     char* whoami() { return name; }
     //
     //   Return number of data entities in structure.
     unsigned long count() { return keycount; }
protected:
     char *name;                    // Name of a particular instance 
                                    //    of a data structure.
     unsigned long keycount;        // Number of data entities in struct
     int (*compare)(void*, void*);  // compare() fn to relate key values
                                    //    of data entities
};

////////////////////////////////////////////////////////////
//   Traverse the structure and apply opfn() to each data 
//   entity in the order generated by next().
////////////////////////////////////////////////////////////
void inline
container::traverse_op(void (*opfn)(void*)) {
     void* data = first();
     while (data) {
          (*opfn)(data);
          data = next();
     }
}

void inline
container::traverse_op(FILE* out, void (*opfn)(FILE*, void*)) {

     void* data = first();

     while (data) {
          (*opfn)(out, data);
          data = next();
     }
}

#endif
