/*----------------------------------------------------------------------------
** Name: mempool.cpp
**
** Title: Memory Pool
**
** Purpose:
**  Create and manage a pool of allocated memory.  Provides:
**    AllocBytes
**    GetString
**    PutBytes
**    PutString
**    PutU32
**  Base class = Table
**
** Status: PRELIMINARY | CODED
**
** $Log:   S:/tbird/arcppc/symbol/mempool.cpv  $
** 
**    Rev 1.3   31 Mar 1998 12:00:34   Winky
** No change.
** 
**    Rev 1.2   12 Mar 1997 14:47:46   hera
** No change.
** 
**    Rev 1.1   03 Mar 1997 15:48:10   hera
** 
**    Rev 1.0   07 Sep 1995 11:16:40   gene
** Initial revision.
** 
**    Rev 1.8   20 Jul 1992 16:19:44   brucea
** Changed: table allocation init and expansion from 4K to 4K*4
** 
**    Rev 1.7   30 Apr 1992 18:42:08   brucea
** Changed: far to FAR for ::GetString declaration
** 
**    Rev 1.6   20 Apr 1992 09:09:06   brucea
** Changed: PutString -> now accepts a string of zero length.  Stores size of 0
**    with no additional data.  The GetString will return a null string for this
**    case.
** 
** 
**    Rev 1.5   06 Dec 1991 17:03:38   john
** Added member function to free the allocated for the symbol table.
** 
**    Rev 1.4   06 Nov 1991 14:38:58   brucea
** Changed retCode test from 0 to SUCCESS
** Fixed size issue with <bytesThrownAway> and assigning a U32 to it
** 
**    Rev 1.3   01 Nov 1991 10:57:54   brucea
** Put #ifdef DEBUG around #ifndef _WINIO_
** 
**    Rev 1.2   12 Sep 1991 14:52:50   brucea
** Created AllocBytes to get N bytes of storage from the memory pool 
** without putting data.  PutBytes now calls AllocBytes and then fills in
** the data.
** 
**    Rev 1.1   11 Sep 1991 18:11:04   john
** PUTU32 only did a PUTU8
** 
**    Rev 1.0   11 Sep 1991 09:09:06   brucea
** Initial revision.
**
** $Header:   S:/tbird/arcppc/symbol/mempool.cpv   1.3   31 Mar 1998 12:00:34   Winky  $
**
** Copyright (C) 1991 Microtek International.  All rights reserved.
**
**--------------------------------------------------------------------------*/

                       /****************************
                        *                          *
                        *       INCLUDE FILES      *
                        *                          *
                        ****************************/

#ifndef _MEMPOOL_
#include "mempool.h"
#endif

#ifdef DEBUG
#ifndef _WINIO_
#include "winio.h"
#endif
#endif
                       /****************************
                        *                          *
                        *        DEFINITIONS       *
                        *                          *
                        ****************************/


#define MEMTABLE_EXPANSION_SIZE 4096L * 4L
#define MEMTABLE_INIT_SIZE      4096L * 4L

MemPool st;

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

//member functions for MemPool

MemPool::MemPool():Table()        // constructor
   {
   availMemOffset = 0L;
   bytesThrownAway = 0;  // initialize member vars

   initialSize = MEMTABLE_INIT_SIZE;
   expandSize  = MEMTABLE_EXPANSION_SIZE;
   };  // end of MemPool constructor


RETCODE MemPool::AllocBytes(U8 size, TABLE_OFFSET& tableDataOffset)
   {
   RETCODE retCode;
   U32  memoryLeft;

   tableDataOffset = 0;    // set to null in case of a memory failure
   if ((memoryLeft = (tableSize-availMemOffset)) < (U32)size)
      {  // not enough space or empty table; must get more
      if ((retCode = InitOrExtendTable(0)) != SUCCESS) return retCode;
      // a non-zero retcode means no memory was found; otherwise fall thru

      else
         { // found more memory;
         // jump over any unused bytes to preserve 64K boundary
         // move pointer past boundary of old partition

         availMemOffset+= memoryLeft;
         bytesThrownAway += (U16)memoryLeft;
         }
      } // end of if that checked for enough memory or retrieved more memory

   // set the return pointer to the head of the data
   tableDataOffset = availMemOffset;

   // bump pointer to available memory by size of data
   availMemOffset += size;

   return SUCCESS;
   }  // end of MemPool::AllocBytes


VOID MemPool::GetString(TABLE_OFFSET tableDataOffset,
                        U8 FAR       *outputString)
   {
   HPU8  symPtr;
   U8    length;

   symPtr = GetHugeDataPtr(tableDataOffset);
   length = *symPtr++;                 // first byte is length
   for (; length > 0; length--)  {
      *outputString++ = *symPtr++;     // copy name one byte at a time
      };
   *outputString = '\0';                 // terminate string
   };  // end of MemPool::MemGetString


VOID MemPool::ObliterateTable(VOID) {
   Table::ObliterateTable();
   availMemOffset = 0L;
   bytesThrownAway = 0;  // initialize member vars

   initialSize = MEMTABLE_INIT_SIZE;
   expandSize  = MEMTABLE_EXPANSION_SIZE;
}

RETCODE MemPool::PutBytes(U8 *inputDataPtr, U8 size,
                          TABLE_OFFSET& tableDataOffset)
   {
   RETCODE retCode;
   HPU8 tempHugePtr;

   retCode = AllocBytes(size, tableDataOffset);
   if (retCode != SUCCESS) return retCode;  // return if some error

   // tableDataOffset points to head of allocated memory
   // calculate pointer to this data
   tempHugePtr = hpTableObject + tableDataOffset;

   // store the data
   for (; size > 0; size--)  {
      *tempHugePtr++ = *inputDataPtr++;
      }
   return SUCCESS;
   }  // end of MemPool::PutBytes


RETCODE MemPool::PutString(LPSTR lpString, TABLE_OFFSET& tableDataOffset)
   {
   RETCODE retCode;
   U32  memoryLeft;
   HPU8 tempHugePtr;
   U16 length;       // length of input string
   U8 i;

   tableDataOffset = 0;    // set to null in case of a memory failure
   length = (U16)lstrlen(lpString);

// removing check for 0 length string; instead, it places size of 0 into
// memory.  GetString will correctly create a NULL return string
//   if (length == 0)  {
//      return ER_STRING_LENGTH_ZERO;
//      }
   length = min(length, 255);    // truncate long strings

   // check for enough memory where requirement is string length plus one
   // byte for the header length byte.

   if ((memoryLeft = (tableSize-availMemOffset)) < (U32)(length + 1))  {
      // not enough space or empty table; must get more
#ifdef DEBUG
      printf("extending st\n");
#endif
      if ((retCode = InitOrExtendTable(0)) != SUCCESS)  return retCode;
      // a non-zero retcode means no memory was found; otherwise fall thru
      else  {
         // found more memory;
         // jump over any unused bytes to preserve 64K boundary
         // move pointer past boundary of old partition

         availMemOffset += memoryLeft;
         bytesThrownAway += (U16)memoryLeft;
         }
      } // end of if that checked for enough memory or retrieved more memory

   // put string into table
   // set the return pointer to the head of the data
   tableDataOffset = availMemOffset;

   // set huge pointer to available memory
   tempHugePtr = hpTableObject + availMemOffset;

   // increment offset pointer, by size of data, to next available memory loc
   availMemOffset += length + 1;

   // store length, then string
   *tempHugePtr++ = (U8)(length);   // put length into first byte
   for (i = 1; i <= length;)  {     // copy rest of string
      *tempHugePtr++ = *lpString++;
      i++;
      }
   return SUCCESS;
   };  // end of MemPool::PutString


RETCODE MemPool::PutU32(U32 data)
   {
   RETCODE retCode;
   U32  memoryLeft;
   HPU8 tempHugePtr;

   if ((memoryLeft = (tableSize-availMemOffset)) < 4)  {
      // not enough space or empty table; must get more
      if ((retCode = InitOrExtendTable(0)) != SUCCESS) return retCode;
      // a non-zero retcode means no memory was found; otherwise fall thru

      else  {
         // found more memory;
         // jump over any unused bytes to preserve 64K boundary
         // move pointer past boundary of old partition

         availMemOffset+= memoryLeft;
         bytesThrownAway += (U16)memoryLeft;
         }
      } // end of "if" that checked for enough memory or retrieved more memory

   // put the bytes into table

   // set huge pointer to available memory
   tempHugePtr = hpTableObject + availMemOffset;

   // bump pointer to available memory by size of data
   availMemOffset += 4;    // increment by size of U32

   // store the data
   *(U32 *)tempHugePtr = data;

   return SUCCESS;
   }  // end of MemPool::PutU32

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