// file: $isip/class/io/SofSymbolTable/SofSymbolTable.h
// version: $Id: SofSymbolTable.h 4788 2000-09-15 19:14:22Z zhao $
//

// make sure definitions are only made once
//
#ifndef ISIP_SOF_SYMBOL_TABLE
#define ISIP_SOF_SYMBOL_TABLE

// isip include files
//
#ifndef ISIP_SYS_STRING
#include <SysString.h>
#endif

// SofSymbolTable: a class to be used under Sof. the symbol table is an
//  array of SysStrings which are the symbol names. it is used to
//  keep track of a symbol table for Sof's use. 
//
class SofSymbolTable {
  
  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:
  
  // define the class name
  //
  static const SysString CLASS_NAME;
  
  //----------------------------------------
  //
  // other important constants
  //
  //----------------------------------------  
  
  // maximum length of a symbol
  //
  static const long MAX_SYM_LENGTH = 64;

  // the size to grow the symbol array by each time
  //
  static const long GROW_SIZE = 256;
  
  // invalid characters within symbol names
  //
  static const SysString INVALID_CHARS;

  // constants for efficiency measure
  //
  static const long MAX_WASTED_SPACE = 1024;
  
  //----------------------------------------
  //
  // default values and arguments
  //
  //----------------------------------------  
  
  // dummy index for a non-exist symbol in the table
  //
  static const long NO_SYMB = -1;

  //----------------------------------------
  //
  // error codes
  //
  //----------------------------------------  

  // class general error
  //
  static const long ERR = 10200;
  
  // error code indicating failure to add a symbol into the symbol table
  //
  static const long ERR_ADD = 10201;
  
  // error code indicating failure to find a symbol in the symbol table
  //
  static const long ERR_NOTFND = 10202;

  // error code indicating no transform vector
  //
  static const long ERR_NOVECT = 10203;
  
  // error code indicating symbol index out of range 
  //
  static const long ERR_SYMB = 10204;
  
  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:
  
  // an array of string symbols
  //
  SysString* table_d;
  
  // number of references to symbols
  //
  long* ref_count_d;			
  
  // current length of the symbol table (some entries may be empty)
  //
  long table_size_d;
  
  // number of non-empty entries in the symbol table
  //
  long num_syms_d;
  
  // capacity of the symbol table, it can be grown dynamically
  //
  long table_capacity_d;
  
  // parameters used to transform between tables
  //
  long* transform_d;		
  long transform_size_d;
  
  // debugging parameters
  //
  Integral::DEBUG debug_level_d;

  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:

  // method: name
  //
  static const SysString& name() {
    return CLASS_NAME;
  }
  
  // other static methods
  //
  static boolean diagnose(Integral::DEBUG debug_level);
  
  // method: setDebug
  //
  boolean setDebug(Integral::DEBUG level) {
    debug_level_d = level;
    return true;
  }

  // other debug methods
  //
  boolean debug(const unichar* msg) const;
 
  // destructor/constructor(s)
  //
  ~SofSymbolTable();
  SofSymbolTable();
  SofSymbolTable(const SofSymbolTable& arg);

  // assign methods
  //
  boolean assign(const SofSymbolTable& arg);
  
  // method: operator=
  //
  SofSymbolTable& operator=(const SofSymbolTable& arg) {
    if (!assign(arg)) {
      Error::handle(name(), L"operator=", Error::ARG,
                    __FILE__, __LINE__);
    }      
    return *this;
  }
  
  // i/o methods:
  //  these methods are omitted because SofSymbolTable can not write itself
  //  to an sof file
  //

  // equality methods:
  //  these methods are omitted because they are not useful for
  //  SofSymbolTable objects
  //

  // memory management methods:
  //  new and delete are omitted because memory for SofSymbolTable objects is
  //  not managed by the MemoryManager class. the clear method does not
  //  accept FREE mode, so the user is forced to use the destructor for
  //  handling the SofSymbolTable. Sof files could easily be corrupted
  //  if the memory of SofSymbolTable is improperly freed.
  //
  boolean clear(Integral::CMODE ctype_a = Integral::DEF_CMODE);

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  extensions to the required public methods
  //
  //---------------------------------------------------------------------------

  // assign methods
  //
  boolean assignCompact(const SofSymbolTable& arg);
  
  // memory size methods
  //
  long memSize() const;

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  symbol table manipulation methods
  //
  //---------------------------------------------------------------------------
  
  // symbol retrieval methods
  //
  long getIndex(const SysString& name) const;
  boolean getSymbol(SysString& name, long num) const;
  long getRefCount(const SysString& name) const;
  long getRefCount(long index) const;

  // method: getCount
  //
  long getCount() const {
    return num_syms_d;
  }
  
  // symbol entry manipulation methods
  //
  long add(const SysString& name);
  boolean add(long index, long refs, const SysString& name);
  
  boolean remove(const SysString& name);
  boolean remove(long index);

  // checkName methods:
  //  this method checks if a symbol name is valid
  //
  boolean checkName(const SysString& name) const;

  // method: isEfficient
  //  this method checks if the symbol table is used efficiently by checking
  //  the number of unused slots 
  //
  boolean isEfficient() const {
    
    // if few spaces are wasted, it is efficient
    //
    return ((table_size_d - num_syms_d) < MAX_WASTED_SPACE);    
  }

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  symbol table conversion methods
  //
  //---------------------------------------------------------------------------

  // convert methods:
  //  these methods get the index of a symbol in this table given its index
  //  in the old table
  //
  long convert(const SofSymbolTable& old, long index) const;
  long convert(long index) const;

  // transform methods:
  //  these methods are for manipulating the transform vector between the
  //  old symbol table and this symbol table
  //
  boolean transformInit(const SofSymbolTable& old);
  boolean transformDelete();

  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:

  // add new symbol methods
  //
  long addNew(const SysString& name);
  
  // grow table capacity methods
  //
  boolean growCapacity();
  
  // release memory methods
  //
  boolean freeMem();
};

// end of include file
// 
#endif
