// $RCSfile: catalog.h,v $
// $State: Exp $ 
// $Revision: 1.1 $
// $Author: roman $
// $Date: 90/07/07 01:54:30 $

/*
 * A catalog is used to efficiently maintain a set of strings.
 */

#ifndef catalog_h
#define catalog_h

struct CatalogEntry {
   char* name;
   int len;
   int references;
   CatalogEntry* chain;
};

typedef CatalogEntry* EntryPtr;

typedef EntryPtr SymbolID;

class Catalog {
 protected:
    struct DeleteEntry {
        CatalogEntry* item;
	unsigned hashvalue;
	DeleteEntry* chain;
    };

    int nelements;
    EntryPtr* first;
    EntryPtr* last;
    DeleteEntry* delfirst;

    unsigned Hash(const char*, int&);
public:

    Catalog(int size=128);
    ~Catalog();

    SymbolID Register(const char*);     // Register the use (reference) of a
					// string.

//  SymbolID Register(SymbolID);        // Register another use (reference) of
					// a string.

    SymbolID Find(const char*);

    void  Unregister(SymbolID);         // Unregister the use (reference) of a
                                        // string.

    char* String (SymbolID id) {        // Access a registered string's string
      register EntryPtr e;              // value.  Also works for strings with
                                        // no registered use if done prior to
      e = EntryPtr(id);                 // DeleteUnregistered().
      return e->name;
    }

    void DeleteUnregistered();          // Delete all strings for which there
                                        // is no registered use.

};

/*
  CatalogIter is a subclass of catalog, allows for iterating through all entries
*/

class CatalogIter : public Catalog {
 protected:
   EntryPtr* chainptr;
   int  nextchain();
   EntryPtr  iter;
   char * nextiter() 
     {
	char *n  = iter->name;
	iter = iter->chain;
	return n;
     } 
 public:
   int reset() { chainptr = first; return nextchain(); }
   char* next(); 
   CatalogIter(int size=128) : Catalog(size) {}
};
   

#endif
