Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

MemStreamer.hpp

Go to the documentation of this file.
00001 /*
00002 This product contains certain software code or other information
00003 ("AT&T Software") proprietary to AT&T Corp. ("AT&T").  The AT&T
00004 Software is provided to you "AS IS".  YOU ASSUME TOTAL RESPONSIBILITY
00005 AND RISK FOR USE OF THE AT&T SOFTWARE.  AT&T DOES NOT MAKE, AND
00006 EXPRESSLY DISCLAIMS, ANY EXPRESS OR IMPLIED WARRANTIES OF ANY KIND
00007 WHATSOEVER, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00008 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, WARRANTIES OF
00009 TITLE OR NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS, ANY
00010 WARRANTIES ARISING BY USAGE OF TRADE, COURSE OF DEALING OR COURSE OF
00011 PERFORMANCE, OR ANY WARRANTY THAT THE AT&T SOFTWARE IS "ERROR FREE" OR
00012 WILL MEET YOUR REQUIREMENTS.
00013 
00014 Unless you accept a license to use the AT&T Software, you shall not
00015 reverse compile, disassemble or otherwise reverse engineer this
00016 product to ascertain the source code for any AT&T Software.
00017 
00018 (c) AT&T Corp. All rights reserved.  AT&T is a registered trademark of AT&T Corp.
00019 
00020 ***********************************************************************
00021 
00022 History:
00023 
00024       24/11/99  - initial release by Hartmut Liefke, liefke@seas.upenn.edu
00025                                      Dan Suciu,      suciu@research.att.com
00026 */
00027 
00028 //**************************************************************************
00029 //**************************************************************************
00030 
00031 // This module contains the memory streamer class
00032 // The memory streamer represents a sequence of memory blocks
00033 // that grows over time. The blocks at the beginning are small, while
00034 // later, larger blocks are allocated.
00035 // The memory streamer is the core of the container implementation
00036 
00037 #ifndef STREAMMEM_HPP
00038 #define STREAMMEM_HPP
00039 
00040 #include <stdlib.h>
00041 #include <stdio.h>
00042 #include <string.h>
00043 
00044 #include "Types.hpp"
00045 
00046 #include "MemMan.hpp"   // The global memory manager
00047 
00048 //**********************************************************************************
00049 
00050 // For the MemStreamer, the block size increase slowly in 16 steps.
00051 // 'blocksizeidxs' contains the block size indices for each step
00052 
00053 #define BLOCKSIZE_IDXNUM 16
00054 extern unsigned char blocksizeidxs[];
00055 
00056 class Output;
00057 
00058 struct MemStreamBlock
00059    // Defines one single data block
00060 {
00061    MemStreamBlock *next;            // The next data block of the same streamer
00062    unsigned long  blocksize:28;     // The size of this block
00063    unsigned long  blocksizeidxidx:4;// The block size index (i.e. the index within blocksizeidxs)
00064    unsigned long  cursize;          // The current number of bytes in this block
00065 
00066 //   MemStreamBlock *myprev,*mynext;   // Previous and next block
00067 //   unsigned long  idx;
00068 
00069    char           data[1];       // The first byte of the data
00070                                  // (The other data comes DIRECTLY afterwards)
00071 };
00072 
00073 //extern MemStreamBlock    *blocklist;
00074    // The list of all blocks
00075 
00076 struct MemStreamMarker
00077    // Represents a marker in the memory stream
00078    // Markers are used so that everything appended to the Streamer
00079    // after the marker can be deleted
00080    // Several markers can exist in the Streamer and they are
00081    // in backwards references in a single-chained list.
00082 {
00083    MemStreamBlock    *block;  // The block of the previous marker,
00084    MemStreamMarker   *pos;    // The pointer to the previous marker
00085                               // The pointers are NULL, if there is no previous marker
00086 };
00087 
00088 class MemStreamer
00089 {
00090    MemStreamBlock    *firstblock;         // The first block of the streamer
00091    MemStreamBlock    *curblock;           // The current block, which is also the last block
00092    unsigned long     overallsize:28;      // The overall size of the memory streamer
00093    unsigned long     curblocksizeidxidx:4;
00094    MemStreamMarker   curmarker;           // The position of the current marker is stored here
00095                                           // If there is no marker, then both pointers are NULL
00096 
00097    void ReleaseBlock(MemStreamBlock *block)
00098       // Releases the block from the mem streamer
00099       // Typically, this is the last block in the chain - but it could
00100       // also be in the middle
00101    {
00102 /*
00103       if(block->myprev!=NULL)
00104          block->myprev->mynext=block->mynext;
00105       else
00106          blocklist=block->mynext;
00107       if(block->mynext!=NULL)
00108          block->mynext->myprev=block->myprev;
00109 */
00110 //      memset(block->data,0xcd,block->cursize);
00111       FreeBlock((char *)block,blocksizeidxs[block->blocksizeidxidx]);
00112    }
00113 
00114    MemStreamBlock *AllocateNewBlock()
00115       // Allocates a new block
00116       // The size is determined by the next index in blocksizeidxs
00117    {
00118       MemStreamBlock *newblock;
00119 
00120       // Let's get the new block
00121       newblock=(MemStreamBlock *)AllocateBlock(blocksizeidxs[curblocksizeidxidx]);
00122 
00123       // The usable data size is the block size - the size of the header
00124       newblock->blocksize=GetBlockSize(blocksizeidxs[curblocksizeidxidx])-(sizeof(MemStreamBlock)-1);
00125       newblock->blocksizeidxidx=curblocksizeidxidx;
00126 
00127       // Do we still have more steps to go in the block size increase?
00128       // => Go to next step
00129       if(curblocksizeidxidx<BLOCKSIZE_IDXNUM-1)
00130          curblocksizeidxidx++;
00131 
00132       newblock->next=NULL;
00133       newblock->cursize=0;
00134 /*
00135       // Let's insert the block at the end of the block-chain
00136       newblock->mynext=blocklist;
00137       if(blocklist!=NULL)
00138          blocklist->myprev=newblock;
00139       newblock->myprev=NULL;
00140       blocklist=newblock;
00141 */
00142       return newblock;
00143    }
00144 
00145 public:
00146 
00147    void Initialize(unsigned long firstblocksizeidx=0)
00148       // Initializes the memstreamer and sets the first block index step
00149    {
00150       if(firstblocksizeidx>=BLOCKSIZE_IDXNUM)
00151          firstblocksizeidx=BLOCKSIZE_IDXNUM-1;
00152 
00153       curblocksizeidxidx=firstblocksizeidx;
00154       overallsize=0;
00155 
00156       curmarker.block=NULL;
00157       curmarker.pos=NULL;
00158 
00159       firstblock=curblock=NULL;
00160    }
00161 
00162    MemStreamer(unsigned long firstblocksizeidx=0)
00163    {
00164       Initialize(firstblocksizeidx);
00165    }
00166 
00167    ~MemStreamer()
00168    {
00169       ReleaseMemory(0);
00170    }
00171 
00172    int GetSize() { return overallsize; }
00173 
00174    MemStreamBlock *GetFirstBlock() { return firstblock; }
00175 
00176    void WordAlign()
00177       // Allocated 1 to 3 bytes to align the current memory pointer
00178       // to an address divisible by 4.
00179    {
00180       if(curblock==NULL)
00181          return;
00182 
00183       int addsize=3-((curblock->cursize+3)&3);
00184       if(addsize>0)
00185       {
00186          curblock->cursize+=addsize;
00187          overallsize+=addsize;
00188       }
00189    }
00190 
00191    char *GetByteBlock(unsigned len)
00192       // The main function for allocated more memory of size 'len'.
00193       // The function checks the current block and if there is not enough space,
00194       // the function 'AllocateNewBlock' is called.
00195    {
00196       if(len+sizeof(MemStreamBlock)-1>LARGEBLOCK_SIZE) // Is the requested size larger than the biggest possible block?
00197       {
00198          char str[100];
00199          sprintf(str,"Could not allocate %lu bytes (largest possible block size=%lu bytes) !",
00200             sizeof(MemStreamBlock)-1+len,
00201             LARGEBLOCK_SIZE);
00202          Error(str);
00203          Exit();
00204       }
00205 
00206       if(curblock==NULL)
00207          // We don't have a block yet ?
00208          firstblock=curblock=AllocateNewBlock();
00209 
00210       if(curblock->blocksize-curblock->cursize>=len)
00211          // Enough space in current block?
00212       {
00213          char *ptr=curblock->data+curblock->cursize;
00214          curblock->cursize+=len;
00215          overallsize+=len;
00216          return ptr;
00217       }
00218       else  // We add a new block at the end
00219       {
00220          do
00221          {
00222             curblock->next=AllocateNewBlock();
00223             curblock=curblock->next;
00224          }
00225          while(curblock->blocksize<len);  // If we don't have enough space,
00226                                           // we simply create a bigger one!
00227 
00228          curblock->cursize=len;
00229          overallsize+=len;
00230 
00231          return curblock->data;
00232       }
00233    }
00234 
00235    void ReleaseByteBlock(unsigned len)
00236       // Removes 'len' bytes from the current block
00237    {
00238       // If the current block is smaller than the data to be removed,
00239       // then there is something really wrong!
00240       if(curblock->cursize<len)
00241       {
00242          Error("Fatal error in ReleaseBlock !\n");
00243          Exit();
00244       }
00245 
00246       curblock->cursize-=len;
00247       overallsize-=len;
00248 
00249 #ifdef RELEASEMEM_SAFE
00250       memset(curblock->data+curblock->cursize,0xcd,len);
00251 #endif
00252    }
00253 
00254 //******************************************************************************
00255 
00256    void StoreData(char *data,unsigned len)
00257       // Stores the a sequence of bytes in the memory streamer
00258       // The bytes can be distributed over many blocks
00259    {
00260       if(curblock==NULL)
00261          // We don't have a block yet ?
00262          firstblock=curblock=AllocateNewBlock();
00263 
00264       while(len>curblock->blocksize-curblock->cursize)
00265          // There is not enough space in the current block ?
00266          // ==> We fill the current block as much as possible
00267       {
00268          mymemcpy(curblock->data+curblock->cursize,data,
00269                   curblock->blocksize-curblock->cursize);
00270 
00271          data        +=curblock->blocksize-curblock->cursize;
00272          overallsize +=curblock->blocksize-curblock->cursize;
00273          len         -=curblock->blocksize-curblock->cursize;
00274          curblock->cursize=curblock->blocksize;
00275 
00276          curblock->next=AllocateNewBlock();
00277 
00278          curblock=curblock->next;
00279       }
00280       mymemcpy(curblock->data+curblock->cursize,data,len);
00281       curblock->cursize+=len;
00282       overallsize+=len;
00283    }
00284 
00285 //******************************************************************************
00286 
00287 // The following auxiliary functions allow the easy storage of simple data values
00288 
00289    void StoreChar(unsigned char c)
00290       // Stores one single character
00291    {
00292       if(curblock==NULL)
00293          // We don't have a block yet ?
00294          firstblock=curblock=AllocateNewBlock();
00295       else
00296       {
00297          if(curblock->blocksize-curblock->cursize==0)
00298             // The block is completely full? ==> Get a new one
00299          {
00300             curblock->next=AllocateNewBlock();
00301             curblock=curblock->next;
00302          }
00303       }
00304       curblock->data[curblock->cursize]=c;
00305       curblock->cursize++;
00306       overallsize++;
00307    }
00308 
00309    void StoreCompressedUInt(unsigned long val,unsigned char offs=0)
00310       // Stores a compressed unsigned integer
00311       // The values below the offset threshold are reserved for other use.
00312       // Hence, the offset is basically added to 'val'.
00313       // The offset *must* be smaller than 128
00314    {
00315       if(val<128-(unsigned)offs)
00316          StoreChar((unsigned char)val+offs);
00317       else
00318       {
00319          if(val<16384)
00320          {
00321             StoreChar((unsigned char)(val>>8)+128);
00322             StoreChar((unsigned char)val);
00323          }
00324          else
00325          {
00326             StoreChar((unsigned char)(val>>24)+192);
00327             StoreChar((unsigned char)(val>>16));
00328             StoreChar((unsigned char)(val>>8));
00329             StoreChar((unsigned char)(val));
00330          }
00331       }
00332    }
00333 
00334    void StoreCompressedSInt(char isneg,unsigned long val)
00335       // Stores a signed integer in compressed format
00336       // The sign is in 'isneg' and 'val' is the basis
00337    {
00338       if(val<64)
00339          StoreChar((unsigned char)val+(isneg ? 64 : 0));
00340       else
00341       {
00342          if(val<8192)
00343          {
00344             StoreChar((unsigned char)(val>>8)+(isneg ? (128+32) : 128));
00345             StoreChar((unsigned char)val);
00346          }
00347          else
00348          {
00349             StoreChar((unsigned char)(val>>24)+(isneg ? (192+32) : 192));
00350             StoreChar((unsigned char)(val>>16));
00351             StoreChar((unsigned char)(val>>8));
00352             StoreChar((unsigned char)val);
00353          }
00354       }
00355    }
00356 
00357    void StoreCompressedSInt(long val)
00358       // Stores a signed integer in compressed format
00359    {
00360       if(val&0x80000000L)
00361          StoreCompressedSInt(1,-(long)val);
00362       else
00363          StoreCompressedSInt(0,val);
00364    }
00365 
00366    void StoreUInt32(unsigned long val)
00367       // Stores a unsigned integer in compressed format
00368    {
00369       StoreCompressedUInt(val);
00370    }
00371 
00372    void StoreSInt32(char isneg,unsigned long val)
00373       // Stores a signed integer in compressed format
00374    {
00375       StoreCompressedSInt(isneg,val);
00376    }
00377 
00378 //**********************************************************************************
00379 //**********************************************************************************
00380 
00381    void StartNewMemBlock()
00382       // Creates a new marker on the memory streamer
00383    {
00384       MemStreamMarker *newmarker=(MemStreamMarker *)GetByteBlock(sizeof(MemStreamMarker));
00385 
00386       *newmarker=curmarker;   // We copy previous marker
00387 
00388       // We save the new marker position
00389       curmarker.block=curblock;
00390       curmarker.pos=newmarker;
00391    }
00392 
00393    void RemoveLastMemBlock()
00394       // Removes a the data up to the last memory marker
00395    {
00396       MemStreamBlock *block,*nextblock;
00397       int            newsize;
00398 
00399       // We remove all blocks after the block of the last marker
00400 
00401       block=curmarker.block->next;
00402 
00403       while(block!=NULL)
00404       {
00405          overallsize-=block->cursize;
00406          nextblock=block->next;
00407          ReleaseBlock(block);
00408          block=nextblock;
00409       }
00410       curmarker.block->next=NULL;
00411 
00412       // We save block pointer -> This block will be truncated to size 'newsize'
00413       block=curblock=curmarker.block;
00414 
00415       // The remaining size
00416       newsize=(char *)curmarker.pos-block->data;
00417 
00418       // We set the marker
00419       curmarker=*(curmarker.pos);
00420 
00421 #ifdef RELEASEMEM_SAFE
00422       // We overwrite the empty space ==> Just for protection
00423       // We can take this out later
00424       memset(block->data+newsize,0xcd,block->cursize-newsize);
00425 #endif
00426 
00427       overallsize-=(block->cursize-newsize);
00428       block->cursize=newsize;
00429 
00430       if(block->blocksizeidxidx<BLOCKSIZE_IDXNUM-1)
00431          // Not the largest block size?
00432          curblocksizeidxidx=block->blocksizeidxidx+1;
00433       else
00434          curblocksizeidxidx=block->blocksizeidxidx;
00435    }
00436 
00437    void ReleaseMemory(unsigned long firstblocksizeidx)
00438       // Releases the entire memory of the memstreamer
00439    {
00440       MemStreamBlock    *block=firstblock,
00441                         *nextblock;
00442       while(block!=NULL)
00443       {
00444          nextblock=block->next;
00445          ReleaseBlock(block);
00446          block=nextblock;
00447       }
00448       Initialize(firstblocksizeidx);
00449    }
00450 
00451    void *operator new(size_t size, MemStreamer *mem)  {  return mem->GetByteBlock(size);  }
00452    void operator delete(void *ptr)  {}
00453 };
00454 
00455 //*********************************************************************
00456 //*********************************************************************
00457 
00458 // For the decompressor, we implement an additional memory management
00459 
00460 /*
00461 #ifdef XDEMILL
00462 
00463 extern MemStreamer blockmem;
00464 
00465 #define MEMBLOCK_THRESHOLD 8000
00466 
00467 extern unsigned char *memoryalloc_buf;
00468 extern unsigned char *memoryalloc_curptr;
00469 extern unsigned long memoryalloc_bufsize;
00470 
00471 inline void SetMemoryAllocationSize(unsigned long allocsize)
00472 {
00473    if(memoryalloc_bufsize<allocsize)
00474    {
00475       if(memoryalloc_buf!=NULL)
00476          free(memoryalloc_buf);
00477 
00478       memoryalloc_buf=(unsigned char *)malloc(allocsize);
00479       if(memoryalloc_buf==NULL)
00480          ExitNoMem();
00481 
00482       memoryalloc_curptr=memoryalloc_buf;
00483 
00484       memoryalloc_bufsize=allocsize;
00485    }
00486    else
00487       memoryalloc_curptr=memoryalloc_buf;
00488 
00489 }
00490 
00491 inline void WordAlignMemBlock()
00492 {
00493    memoryalloc_curptr=
00494       (unsigned char *)
00495       (((unsigned long)memoryalloc_curptr+3)&0xFFFFFFFCL);
00496 }
00497 
00498 inline unsigned char *AllocateMemBlock(unsigned long size)
00499 {
00500    memoryalloc_curptr+=size;
00501    if(memoryalloc_curptr>memoryalloc_buf+memoryalloc_bufsize)
00502    {
00503       Error("Fatal Error!");
00504       Exit();
00505    }
00506    return memoryalloc_curptr-size;
00507 }
00508 
00509 inline void FreeMemBlock(void *ptr,unsigned long size)
00510 {
00511 }
00512 */
00513 //#endif
00514 
00515 #endif

Generated on Sat Oct 13 16:08:39 2001 for XMILL by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001