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

EnumCompress.cpp

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 Enumeration-Compressor 'e'
00032 // The enumeration-compressor (or dictionary compressor) assigns a
00033 // positive integer to each possible string occured. In the compressor,
00034 // a dictionary of all previously seen strings is maintained and a hashtable
00035 // allows the efficient lookup. A new
00036 // string is assigned the next free number.
00037 
00038 // The decompressor loads the dictionary and directly accesses the
00039 // dictionary for a given integer.
00040 
00041 // Note that there is *only one* hashtable for all enum-compressors !!
00042 // I.e. all new strings are represented in the same hash tableindex number space !
00043 
00044 #include "CompressMan.hpp"
00045 
00046 #ifdef XDEMILL
00047 #include "UnCompCont.hpp"
00048 #include "SmallUncompress.hpp"
00049 #endif
00050 
00051 extern MemStreamer blockmem;
00052 
00053 #define SMALLCOMPRESS_THRESHOLD  1024
00054 
00055 //unsigned long     enuminstancecount=0;
00056 
00057 // The MemStreamer used for storing the hashtable entries in the compressor
00058 // and the compressor states in the decompressor
00059 #define enumcompressmem (&blockmem)
00060 
00061 //*************************************************************
00062 
00063 // The compressor is based on a hash table implementation
00064 
00065 #ifdef XMILL
00066 
00067 // The size of the hash table
00068 #define ENUMHASHTABLE_SIZE  32768
00069 #define ENUMHASHTABLE_MASK  32767
00070 #define ENUMHASHTABLE_SHIFT 15
00071 
00072 struct EnumCompressState;
00073 
00074 struct EnumHashEntry
00075    // Stores a hash entry
00076 {
00077    EnumHashEntry     *nextsamehash; // The next entry with the same hash index
00078    unsigned short    datalen;       // The length of the string
00079    char              *dataptr;      // The pointer to the string
00080                                     // Strings are stored in a separate MemStreamer!
00081    EnumCompressState *enumstate;    // The pointer to the state of the compressor
00082    unsigned          localidx;      // The index number for this string
00083                                     // This number is unique within a given compressor state
00084 
00085    void *operator new(size_t size)
00086    {
00087       return enumcompressmem->GetByteBlock(size);
00088    }
00089 
00090    char *GetStrPtr() {  return dataptr;   }
00091 };
00092 
00093 //**************************
00094 
00095 class EnumHashTable
00096    // The hash table implementation
00097 {
00098    static EnumHashEntry    *hashtable[ENUMHASHTABLE_SIZE];
00099    static char             isinitialized;
00100 
00101    static inline unsigned CalcHashIdx(char *str,int len)
00102       // Computes the hash index for a given string
00103    {
00104       unsigned idx=len;
00105       while(len--)
00106       {
00107          idx=(idx<<3)+(idx>>29)+(idx>>(idx&1));
00108          idx+=(unsigned char)*str;
00109          str++;
00110       }
00111       return (idx+(idx>>ENUMHASHTABLE_SHIFT))&ENUMHASHTABLE_MASK;
00112    }
00113 
00114 public:
00115 
00116    EnumHashTable()
00117    {
00118       isinitialized=0;
00119    }
00120 
00121    static void Initialize()
00122       // The hash table is emptied
00123    {
00124       if(isinitialized==0)
00125       {
00126          for(int i=0;i<ENUMHASHTABLE_SIZE;i++)
00127             hashtable[i]=NULL;
00128 
00129          isinitialized=1;
00130       }
00131    }
00132 
00133    static void Reset()
00134       // This will cause the hash table to be emptied next time we try to
00135       // add elements
00136    {
00137       isinitialized=0;
00138    }
00139 
00140    static EnumHashEntry *FindOrCreateEntry(char *str,int len,EnumCompressState *enumstate,char *isnew,MemStreamer *strmem)
00141       // Finds or creates a new hash entry
00142       // enumstate is the state for the compressor, *isnew will be set to 1 if a new entry has been created
00143       // strmem is the MemStreamer used for allocating string memory space
00144    {
00145       // Let's determine the hash table index first
00146       unsigned       hashidx=CalcHashIdx(str,len);
00147       EnumHashEntry  **hashentryref=hashtable+hashidx;
00148       char           *ptr1,*ptr2;
00149 //      int            i;
00150 
00151       // Let's firstly look through the existing hash index list
00152       while(*hashentryref!=NULL)
00153       {
00154          if(((*hashentryref)->datalen==len)&&
00155             ((*hashentryref)->enumstate==enumstate))
00156          {
00157             ptr1=str;
00158             ptr2=(*hashentryref)->GetStrPtr();
00159 
00160             // Let's check whether the strings are equal
00161             if(mymemcmp(ptr1,ptr2,len)==0)
00162                // Did we find an entry? ==> We are done
00163             {
00164                *isnew=0;
00165                return *hashentryref;
00166             }
00167          }
00168          hashentryref=&((*hashentryref)->nextsamehash);
00169       }
00170 
00171       // None of the hash-entries matches ?
00172       // ==> We create a new one
00173 
00174       *hashentryref=new EnumHashEntry();
00175 
00176       (*hashentryref)->nextsamehash =NULL;
00177       (*hashentryref)->enumstate    =enumstate;
00178 
00179       // The length of the string is stored in 'strmem'
00180       strmem->StoreUInt32(len);
00181 
00182       // Now we allocate the number of bytes in MemStreamer 'strmem'
00183       (*hashentryref)->datalen      =len;
00184       (*hashentryref)->dataptr      =strmem->GetByteBlock(len);
00185 
00186       // Hence, 'strmem' contains a sequence of tuples (len,str) that allows us in the
00187       // decompressor to reconstruct the dictionary
00188       memcpy((*hashentryref)->dataptr,str,len);
00189 
00190       // The item is new
00191       *isnew=1;
00192 
00193       return *hashentryref;
00194    }
00195 };
00196 
00197 EnumHashTable  enumhashtable;
00198 EnumHashEntry  *EnumHashTable::hashtable[ENUMHASHTABLE_SIZE];
00199 char           EnumHashTable::isinitialized;
00200 
00201 //********************************************************************************
00202 //********************************************************************************
00203 //********************************************************************************
00204 
00205 // The actual compressor implementation follows now
00206 
00207 struct EnumCompressState
00208    // The state for each enum-compressor 
00209 {
00210    unsigned long     curidx;              // The number of already assigned strings
00211                                           // This is also the next available index
00212    MemStreamer       stringmem;           // The memory streamer used for storing
00213                                           // the strings
00214    unsigned long     compressed_size;     // We keep track of the number of compressed bytes ...
00215    unsigned long     uncompressed_size;   // ... and uncompressed bytes
00216    EnumCompressState *next;               // All enumstates are kept in a global list
00217                                           // Points to the next enumstate in the global list
00218 };
00219 
00220 //********************************************************************************
00221 
00222 void AddEnumCompressState(EnumCompressState *state);
00223    // This auxiliary function registeres a new compressor state 'state'
00224    // within the EnumCompressFactory
00225 
00226 //********************************************************************************
00227 
00228 class EnumerationCompressor : public UserCompressor
00229    // The actual compressor
00230 {
00231 public:
00232    EnumerationCompressor()
00233    {
00234       datasize=sizeof(EnumCompressState);
00235       contnum=1;
00236       isrejecting=0;
00237       canoverlap=1;
00238       isfixedlen=0;
00239    }
00240 
00241    void InitCompress(CompressContainer *cont,char *dataptr)
00242       // Initializes the compressor the specific enum state 'dataptr'
00243    {
00244       ((EnumCompressState *)dataptr)->curidx=0; // We start at index 0
00245 
00246       // Let's initializes the MemStreamer -
00247       // this is the same as calling the constructor
00248       ((EnumCompressState *)dataptr)->stringmem.Initialize(0);
00249 
00250       // The state is added to a list of states
00251       // This is necessary so that we can store the state information as soon
00252       // as the data is about to be compressed
00253       AddEnumCompressState((EnumCompressState *)dataptr);
00254 
00255       // We also need to initialize the hash table (if it hasn't been initialized before)
00256       EnumHashTable::Initialize();
00257    }
00258 
00259    void CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr)
00260       // Compresses a specific string item
00261    {
00262       char isnew;
00263 
00264       // Let's lookup the item in the hash table
00265       EnumHashEntry *entry=EnumHashTable::FindOrCreateEntry(
00266          str,len,(EnumCompressState *)dataptr,
00267          &isnew,&(((EnumCompressState *)dataptr)->stringmem));
00268       
00269       if(isnew)   // Is this a new entry? ==> We need to assign a new index
00270       {
00271          entry->localidx=((EnumCompressState *)dataptr)->curidx;
00272          ((EnumCompressState *)dataptr)->curidx++;
00273       }
00274       // If the item is not new, then EnumCompressState::curidx is the
00275       // index of the corresponding string
00276 
00277       // We store the index of the item in the container
00278       cont->StoreCompressedUInt(entry->localidx);
00279    }
00280 
00281    // Note that we don't implement the 'FinishCompress' method for UserCompressors.
00282    // The reason is that we do the actual storage in the EnumCompressFactory-class.
00283 
00284    void PrintCompressInfo(char *dataptr,unsigned long *overalluncomprsize,unsigned long *overallcomprsize)
00285       // Prints statistical information about how well the compressor compressed
00286       // the data
00287    {
00288       unsigned long  uncompsize=((EnumCompressState *)dataptr)->uncompressed_size,
00289                      compsize=((EnumCompressState *)dataptr)->compressed_size;
00290 
00291       *overalluncomprsize+=uncompsize;
00292       *overallcomprsize+=compsize;
00293 
00294       if(compsize!=0)
00295          printf("       Enum: %8lu ==> %8lu (%f%%)\n",
00296             uncompsize,compsize,
00297             100.0f*(float)compsize/(float)uncompsize);
00298       else
00299          printf("       Enum: %8lu ==> Small...\n",uncompsize);
00300    }
00301 };
00302 
00303 #endif // XMILL
00304 
00305 //**************************************************************************
00306 //**************************************************************************
00307 //**************************************************************************
00308 
00309 // The Enum-Decompress
00310 
00311 struct EnumDictItem
00312    // Represents an entry in the dictionary
00313    // The entries are stored in a sequence in memory
00314 {
00315    unsigned long  len;
00316    unsigned char  *dataptr;
00317 };
00318 
00319 #ifdef XDEMILL
00320 
00321 struct EnumUncompressState
00322    // The state of the decompressor
00323 {
00324    unsigned long  itemnum;       // The number of items
00325    unsigned long  size;          // The size of the dictionary
00326    EnumDictItem   *itemarray;    // The array of dictionary items
00327    unsigned char  *strbuf;       // The pointer to the string buffer
00328 };
00329 
00330 //********************************************************************************
00331 
00332 
00333 class EnumerationUncompressor : public UserUncompressor
00334 {
00335    EnumUncompressState *GetNextPossibleEnumUnCompressState();
00336       // This auxiliary function returns the next state from the sequence of states
00337       // that was previously loaded from the compressed file
00338       // The sequence of states is stored in the EnumCompressFactory-object
00339 
00340 public:
00341 
00342    EnumerationUncompressor()
00343    {
00344       datasize=sizeof(EnumUncompressState);
00345       contnum=1;
00346    }
00347 
00348    void InitUncompress(UncompressContainer *cont,char *dataptr)
00349       // Initializes the compressor by simply retrieving the next
00350       // state from the list of states
00351    {
00352       *(EnumUncompressState *)dataptr=*GetNextPossibleEnumUnCompressState();
00353    }
00354 
00355    void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *output)
00356       // An item is decompressed by looking up the dictionary
00357    {
00358       unsigned idx=cont->LoadUInt32();
00359       EnumDictItem *item=((EnumUncompressState *)dataptr)->itemarray+idx;
00360 
00361       output->characters((char *)item->dataptr,item->len);
00362    }
00363 };
00364 
00365 
00366 #endif
00367 
00368 //**************************************************************************
00369 
00370 class EnumerationCompressorFactory : public UserCompressorFactory
00371    // The actual enum compressor factory
00372 {
00373    unsigned                   enuminstancecount;   // The number of enum compressor instantiations
00374 
00375    // **** Additional information for the compressor
00376 #ifdef XMILL
00377    EnumerationCompressor      enumcompress;     // We need only one compressor instance
00378    
00379    EnumCompressState          *enumstatelist,   // The global list of enumstates
00380                               **lastenumstateref;
00381 #endif
00382 
00383    // **** Additional information for the decompressor
00384 #ifdef XDEMILL
00385    EnumerationUncompressor    enumuncompress;   // We need only one decompressor instance
00386 
00387    // We keep a temporary array of states for the decompressors
00388    // The factory fills the array by decompressing the status information
00389    // from the input file. The actual states of the decompressors are then
00390    // initialized with these states
00391    EnumUncompressState        *enumuncompressstates;        
00392    unsigned long              activeenumuncompressstates;   // The number of states in the array
00393 #endif
00394 
00395 public:
00396    EnumerationCompressorFactory()
00397    {
00398       enuminstancecount=0;
00399 
00400 #ifdef XMILL
00401       enumstatelist=NULL;
00402       lastenumstateref=&enumstatelist;
00403 #endif
00404 
00405 #ifdef XDEMILL
00406       activeenumuncompressstates=0;
00407 #endif
00408    }
00409 
00410    char *GetName()         {  return "e"; }
00411    char *GetDescription()  {  return "Compressor for small number of distinct data values"; }
00412    char IsRejecting()      {  return 0;   }
00413    char CanOverlap()       {  return 1;   }
00414 
00415    // ******* For the compressor **************
00416 #ifdef XMILL
00417 
00418    void AddEnumCompressState(EnumCompressState *state)
00419       // Adds a new enumstate to the global list
00420    {
00421       *lastenumstateref=state;
00422       lastenumstateref=&(state->next);
00423       state->next=NULL;
00424       enuminstancecount++;
00425    }
00426 
00427    UserCompressor *InstantiateCompressor(char *paramstr,int len)
00428       // The instantiation simply return the one instance we have
00429    {
00430       if(paramstr!=NULL)
00431       {
00432          Error("Enumeration compressor 'e' should not have any arguments ('");
00433          ErrorCont(paramstr,len);
00434          Error("')");
00435          return NULL;
00436       }
00437       return &enumcompress;
00438    }
00439 #endif
00440 
00441    // ******* For the decompressor **************
00442 
00443 #ifdef XDEMILL
00444    UserUncompressor *InstantiateUncompressor(char *paramstr,int len)
00445       // The instantiation simply return the one instance we have
00446    {
00447       return &enumuncompress;
00448    }
00449 #endif
00450 
00451    // The compression/decompression routines for the factory
00452    // CompressFactoriess are also allowed to store status information
00453    // in the compressed file ! The following procedure as used for
00454    // compressing/decompressing this information
00455    // Small data (<1024Bytes) is stored in the header, while
00456    // lare data is stored in separate zlib-blocks in the output file
00457 
00458 #ifdef XMILL
00459    void CompressSmallGlobalData(Compressor *compressor)
00460       // Compresses the small data
00461    {
00462       MemStreamer       headmem;
00463       EnumCompressState *state=enumstatelist;
00464 
00465       // Let's store the number of enum compressor we have
00466       headmem.StoreUInt32(enuminstancecount);
00467 
00468       // For each state, we store the number of dictonary entries and
00469       // the size of the string memory
00470       while(state!=NULL)
00471       {
00472          headmem.StoreUInt32(state->curidx);
00473          headmem.StoreUInt32(state->stringmem.GetSize());
00474 
00475          state=state->next;
00476       }
00477 
00478       compressor->CompressMemStream(&headmem);
00479 
00480       // Next, we also store all dictionary that are smaller than 'SMALLCOMPRESS_THRESHOLD'
00481       state=enumstatelist;
00482 
00483       while(state!=NULL)
00484       {
00485          if(state->stringmem.GetSize()<SMALLCOMPRESS_THRESHOLD)
00486             compressor->CompressMemStream(&(state->stringmem));
00487          state=state->next;
00488       }
00489    }
00490 
00491    void CompressLargeGlobalData(Output *output)
00492       // Compresses the large dictionaries
00493       // Furthermore, we also release all the memory of all (also the small) dictionaries
00494    {
00495       EnumCompressState *state=enumstatelist;
00496       Compressor        compressor(output);
00497       unsigned long     idx=0,uncompressedsize;
00498 
00499       state=enumstatelist;
00500 
00501       while(state!=NULL)
00502       {
00503          // We keep the uncompressed size for the statistical output at the
00504          // end of the compression
00505          state->uncompressed_size=state->stringmem.GetSize();
00506 
00507          if(state->stringmem.GetSize()>=SMALLCOMPRESS_THRESHOLD)
00508          {
00509             compressor.CompressMemStream(&state->stringmem);
00510             compressor.FinishCompress(&uncompressedsize,&(state->compressed_size));
00511             // We store the compressed size in 'state->compressed_size'
00512          }
00513          else
00514             state->compressed_size=0;
00515 
00516          // Releases the memory of the dictionaries
00517          state->stringmem.ReleaseMemory(0);
00518 
00519          state=state->next;
00520          idx++;
00521       }
00522 
00523       // We reset the hash table
00524       // Note that the hash entries themselves are deleted separately by releasing
00525       // the memory of 'blockmem'
00526       EnumHashTable::Reset();
00527       enumstatelist=NULL;
00528       lastenumstateref=&enumstatelist;
00529       enuminstancecount=0;
00530    }
00531 
00532    unsigned long GetGlobalDataSize()
00533       // Determines how much memory we need for the dictionaries
00534       // This information is later used in the decompression to allocate
00535       // the appropriate amount of memory
00536    {
00537       EnumCompressState *state=enumstatelist;
00538       unsigned long     size=0;
00539 
00540       while(state!=NULL)
00541       {
00542          size+=sizeof(EnumDictItem)*state->curidx+          // The size of the dictionary directoy
00543                   WordAlignUInt(state->stringmem.GetSize());// The size of the string space (word-aligned)
00544          state=state->next;
00545       }
00546       return size;
00547    }
00548 #endif
00549 
00550 //*************************************************************************
00551 //*************************************************************************
00552 
00553 #ifdef XDEMILL
00554    void UncompressSmallGlobalData(SmallBlockUncompressor *uncompressor)
00555    {
00556       MemStreamer       headmem;
00557       unsigned long     idx=0,i,j;
00558       unsigned char     *srcptr,*ptr;
00559       EnumDictItem      *curitem;
00560 
00561       // First, let's extract the number of enum states
00562       enuminstancecount=uncompressor->LoadUInt32();
00563 
00564       // We allocate the space for the enum states
00565       enumuncompressstates=(EnumUncompressState *)enumcompressmem->GetByteBlock(sizeof(EnumUncompressState)*enuminstancecount);
00566 
00567       // For each state, we load the number of items and the size of the
00568       // string space
00569       for(i=0;i<enuminstancecount;i++)
00570       {
00571          enumuncompressstates[i].itemnum=uncompressor->LoadUInt32();
00572          enumuncompressstates[i].size=uncompressor->LoadUInt32();
00573       }
00574 
00575       // We align the main memory block of the decompressor
00576       WordAlignMemBlock();
00577 
00578       for(i=0;i<enuminstancecount;i++)
00579       {
00580          // Let's firstly load the small dictionaries
00581          if(enumuncompressstates[i].size<SMALLCOMPRESS_THRESHOLD)
00582          {
00583             // Load the data. Afterwards, 'srcptr' points to the corresponding memory
00584             srcptr=uncompressor->LoadData(enumuncompressstates[i].size);
00585 
00586             // Let's allocate the memory
00587             enumuncompressstates[i].strbuf=AllocateMemBlock(enumuncompressstates[i].size);
00588             WordAlignMemBlock();
00589             memcpy(enumuncompressstates[i].strbuf,srcptr,enumuncompressstates[i].size);
00590 
00591             ptr=enumuncompressstates[i].strbuf;
00592 
00593             // Let's now create the lookup array
00594             enumuncompressstates[i].itemarray=(EnumDictItem *)AllocateMemBlock(sizeof(EnumDictItem)*enumuncompressstates[i].itemnum);
00595 
00596             curitem=enumuncompressstates[i].itemarray;
00597 
00598             // We initialize the lookup array with pointers to the actual strings
00599             for(j=0;j<enumuncompressstates[i].itemnum;j++)
00600             {
00601                // Let's read the length first
00602                curitem->len=LoadUInt32(ptr);
00603                // Let's read the data
00604                curitem->dataptr=LoadData(ptr,curitem->len);
00605                // 'ptr' is moved forward by these operations
00606 
00607                curitem++;
00608             }
00609             // The pointer does not match the predicted size?
00610             // ==> We have a problem.
00611             if(ptr!=enumuncompressstates[i].strbuf+enumuncompressstates[i].size)
00612                ExitCorruptFile();
00613          }
00614       }
00615       // THe number of initializes enum states is zero at the beginning
00616       // The number increases with each call of 'UnCompresssor::UncompressInit()'
00617       activeenumuncompressstates=0;
00618    }
00619 
00620    void UncompressLargeGlobalData(Input *input)
00621       // Uncompresses the large dictionaries
00622    {
00623       unsigned long  i,j,tmpsize;
00624       unsigned char  *ptr;
00625       EnumDictItem   *curitem;
00626 
00627       Uncompressor   uncompressor;
00628 
00629       WordAlignMemBlock();
00630 
00631       for(i=0;i<enuminstancecount;i++)
00632       {
00633          if(enumuncompressstates[i].size>=SMALLCOMPRESS_THRESHOLD)
00634          {
00635             // Let's allocate the memory for the large block
00636             enumuncompressstates[i].strbuf=AllocateMemBlock(enumuncompressstates[i].size);
00637             WordAlignMemBlock();
00638 
00639             tmpsize=enumuncompressstates[i].size;
00640 
00641             // Let's do the actual uncompression
00642             if(uncompressor.Uncompress(input,enumuncompressstates[i].strbuf,&tmpsize))
00643                ExitCorruptFile();
00644 
00645             // Did we uncompress less data than expected? ==> Error
00646             if(tmpsize!=enumuncompressstates[i].size)
00647                ExitCorruptFile();
00648 
00649             ptr=enumuncompressstates[i].strbuf;
00650 
00651             // Let's now create the lookup array
00652             enumuncompressstates[i].itemarray=(EnumDictItem *)AllocateMemBlock(sizeof(EnumDictItem)*enumuncompressstates[i].itemnum);
00653 
00654             curitem=enumuncompressstates[i].itemarray;
00655             
00656             // We initialize the lookup array with pointers to the actual strings
00657             for(j=0;j<enumuncompressstates[i].itemnum;j++)
00658             {
00659                // Let's read the length first
00660                curitem->len=LoadUInt32(ptr);
00661                // Let's read the data
00662                curitem->dataptr=LoadData(ptr,curitem->len);
00663 
00664                // 'ptr' is moved forward by these operations
00665                curitem++;
00666             }
00667             // The pointer does not match the predicted size?
00668             // ==> We have a problem.
00669             if(ptr!=enumuncompressstates[i].strbuf+enumuncompressstates[i].size)
00670                ExitCorruptFile();
00671          }
00672       }
00673    }
00674 
00675    EnumUncompressState *GetNextPossibleEnumUnCompressState()
00676       // Retrieves the next state from the sequence of states
00677       // The next call retrieves the next state and so on.
00678    {
00679       activeenumuncompressstates++;
00680       return enumuncompressstates+activeenumuncompressstates-1;
00681    }
00682 
00683    void FinishUncompress()
00684       // Releases the memory after decompression
00685    {
00686       for(unsigned long i=0;i<enuminstancecount;i++)
00687       {
00688          FreeMemBlock(enumuncompressstates[i].strbuf,enumuncompressstates[i].size);
00689          FreeMemBlock(enumuncompressstates[i].itemarray,sizeof(EnumDictItem)*enumuncompressstates[i].itemnum);
00690       }
00691    }
00692 #endif
00693 };
00694 
00695 EnumerationCompressorFactory  enumcompressfactory;
00696 
00697 #ifdef XMILL
00698 void AddEnumCompressState(EnumCompressState *state)
00699 {
00700    enumcompressfactory.AddEnumCompressState(state);
00701 }
00702 #endif
00703 
00704 #ifdef XDEMILL
00705 EnumUncompressState *EnumerationUncompressor::GetNextPossibleEnumUnCompressState()
00706 {
00707    return enumcompressfactory.GetNextPossibleEnumUnCompressState();
00708 }
00709 #endif

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