
/***************************************************************************
**
**    $Header:   D:/EP196/SRC/LOG/SYMSVR/SYMINDEX.CPP   1.0   15 Aug 1997 14:04:16   ZJRD  $
**
**    $Log:   D:/EP196/SRC/LOG/SYMSVR/SYMINDEX.CPP  $
** 
**    Rev 1.0   15 Aug 1997 14:04:16   ZJRD
** Initial revision.
** 
****************************************************************************/

/*-------------------------------------------------------------------------
** Name: SYMINDEX.CPP
**
** Title: Index Table
**
** Purpose:
**  Supports the creation of a Base Index Table and Type Index Table and
**  provides methods for adding an index and retrieving an offset for an index
**
**  Base class = table
**
** Status: PRELIMINARY
**
** $Log$
** 
** $Header:   D:/EP196/SRC/LOG/SYMSVR/SYMINDEX.CPP   1.0   15 Aug 1997 14:04:16   ZJRD  $
**
** Copyright (C) 1995 Microtek International.  All rights reserved.
**
**------------------------------------------------------------------------*/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/
#include "stdafx.h"                      
#include "symindex.h"
#include "sympool.h"

#ifdef DEBUG
#include <stdio.h>
#endif
                       /****************************
                        *                          *
                        *        DEFINITIONS       *
                        *                          *
                        ****************************/


#define INDEXTABLE_INIT_SIZE      (4L * 256L)
#define INDEXTABLE_EXPANSION_SIZE (4L * 256L)
#define MAX_INDEX_SIZE           0xFFFFFFFFL // this is the max size of any
                                             // index table;  If desired to be
                                             // smaller, inherited class must
                                             // set smaller;
                                             // e.g. BaseIndexTable

                       /****************************
                        *                          *
                        *     EXECUTABLE CODE      *
                        *                          *
                        ****************************/

//member functions for IndexTable

IndexTable::IndexTable():Table()      // constructor with no params
   {
   entryCount = 0L;  // initialize member vars
   initialSize = INDEXTABLE_INIT_SIZE;
   expandSize  = INDEXTABLE_EXPANSION_SIZE;
   maxIndex = MAX_INDEX_SIZE;
   }   // end of IndexTable constructor


//------------------------------------------------------------------------
// IndexTable::AddIndex
//
// Purpose:
//    Add an index into the index table with its offset to the item.
//
// Input parameters:
//    index: TABLE_OFFSET index into index table.
//    itemOffset: offset into the symbol table to be stored at table[index]
//
// Output parameters: None
//
// Error:
//    Reports ER_INDEX_ALREADY_EXISTS if the index already has a legitimate
//    value in the index location in the table.
//    Reports ER_INDEX_OUT_OF_BOUNDS if the requested index is larger than
//       the maximum table size
//
// Pseudo-code for allocation
//    if table not alloc'ed yet, set up to alloc on 256 byte boundary that
//       includes requested index
//    if table alloc'ed, set up to realloc on 256 byte boundary, also to
//       include requested index
//    if table alloc'ed, must set expandSize = additional amount to extend
//       table by
//------------------------------------------------------------------------
RETCODE IndexTable::AddIndex(TABLE_INDEX index, TABLE_OFFSET itemOffset) {

   HP_TABLE_OFFSET hpTable;
   U32 tmpTableSize;
   RETCODE retCode;
   TABLE_INDEX indexPlus1;

   indexPlus1 = index + 1;
   if (indexPlus1 > maxIndex) return ER_INDEX_OUT_OF_BOUNDS;
   // index starts at 0; must incr to calculate the number of bytes needed
   // at that point in the array before testing for greater than tableSize
   if (((indexPlus1) * (sizeof(TABLE_OFFSET))) > tableSize) {
      // must expand table to accommodate new index

      // calculate needed table size and round up (will add extra 256 if it
      // is initially on an even 256 boundary)
      tmpTableSize = (indexPlus1 * (sizeof(TABLE_OFFSET)) + 256)
                     & 0xFFFFFF00L;

      if (!tableSize)  {     // table has not been allocated yet
         initialSize = max(initialSize, tmpTableSize);
         }
      else {
        // must convert absolute request to relative size increase;
        // subtract the present table size from the requested size
        // to come up with the amount to expand the table by
         tmpTableSize = tmpTableSize - tableSize;
         expandSize = max(expandSize, tmpTableSize);
         }
      // allocate the memory for new table
      if ((retCode =
         InitOrExtendTable(GMEM_ZEROINIT)) == ER_SYM_OUT_OF_MEMORY) {
         return retCode;
         }
      }
   // memory available; store itemOffset if one is not already there
   hpTable = (HP_TABLE_OFFSET)GetHugeDataPtr(index * (sizeof(TABLE_OFFSET)));
   if (!*hpTable)  {
      *hpTable = itemOffset;  // save offset to item in symbol table
      entryCount++;
      return SUCCESS;
      }
   else
      return ER_INDEX_ALREADY_EXISTS;
   }   // end of AddIndex


//------------------------------------------------------------------------
// IndexTable::GetOffset
//
// Purpose:
//    Retrieve offset to item in symbol table given the index to the index
//    table.
//
// Input parameters:
//    index:
//       TABLE_OFFSET index into index table; the index is to the size
//       of a TABLE_OFFSET
//
// Output parameters:
//    itemOffset:
//       offset into symbol table of item
//
// Error:
//    Reports ER_INDEX_NOT_IN_TABLE if the index field is NULL
//    Reports ER_INDEX_OUT_OF_BOUNDS if the requested index is larger than
//       the maximum index parameter allowed (it is not depended on table
//       size because the table can be alloc'ed bigger).
//------------------------------------------------------------------------
 RETCODE IndexTable::GetOffset(TABLE_INDEX index,
                               TABLE_OFFSET& itemOffset) {

   if ((index + 1) > maxIndex)
      return ER_INDEX_OUT_OF_BOUNDS;
   else if ((index + 1) > (tableSize / (sizeof(TABLE_OFFSET)))) {
      return ER_TABLE_SMALLER_THAN_INDEX; }
   else {
      itemOffset =
         *(HP_TABLE_OFFSET)GetHugeDataPtr(index * (sizeof(TABLE_OFFSET)));
      if (!itemOffset)  // if NULL then item not in table
         return ER_INDEX_NOT_IN_TABLE;
      else
         return SUCCESS;
      }
   }   // end of GetOffset


//------------------------------------------------------------------------
// IndexTable::ObliterateTable
//------------------------------------------------------------------------
VOID IndexTable::ObliterateTable(VOID) {

   Table::ObliterateTable();
   entryCount = 0L;  // initialize member vars
   initialSize = INDEXTABLE_INIT_SIZE;
   expandSize  = INDEXTABLE_EXPANSION_SIZE;
   maxIndex = MAX_INDEX_SIZE;

}  // end of IndexTable::ObliterateTable


//------------------------------------------------------------------------
// IndexTable::UpdateOffset
//------------------------------------------------------------------------
RETCODE IndexTable::UpdateOffset(TABLE_INDEX index, TABLE_OFFSET newOffset) {

   HPU8 offsetPtr;
   
   if ((index + 1) > maxIndex)
      return ER_INDEX_OUT_OF_BOUNDS;
   else if ((index + 1) > (tableSize / (sizeof(TABLE_OFFSET)))) {
      return ER_TABLE_SMALLER_THAN_INDEX;
   } else {
      offsetPtr = GetHugeDataPtr(index * (sizeof(TABLE_OFFSET)));
      if (! (U32 *) offsetPtr)  // if NULL then item not in table
         return ER_INDEX_NOT_IN_TABLE;
      else
         *(U32 *)offsetPtr = newOffset;
         return SUCCESS;
   }
}  // end of IndexTable::UpdateOffset

/******************************** E O F ****************************/
