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

DivCompress.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 Division-Compressor 'seq'
00032 // The Div-compressor compresses a string by applying a sequence of subcompressors
00033 // to the string. The substrings for the compressors are separated by some delimiter strings
00034 
00035 #include "CompressMan.hpp"
00036 
00037 #ifdef XDEMILL
00038 #include "UnCompCont.hpp"
00039 #endif
00040 
00041 struct DivCompressorItem
00042    // Each subcompressor and the following delimiter string
00043    // are stored in a 'DivCompressorItem'
00044 {
00045    DivCompressorItem *next;               // The next subcompressor item
00046 #ifdef XMILL
00047    UserCompressor    *usercompressor;     // The sub compressor
00048 #endif
00049 #ifdef XDEMILL
00050    UserUncompressor  *useruncompressor;   // The sub decompressor
00051 #endif
00052 
00053    // The separator between subcompressors
00054    // This can be empty (afterseparator=NULL), if this is the last subcompressor
00055    // and there is no separator string at the end
00056    char              *afterseparator;
00057    unsigned short    afterseparatorlen;
00058 
00059    unsigned short    curitemlen;          // After parsing a string, we keep the
00060                                           // length of the string that matches the compressor
00061                                           // 'usercompressor'
00062 
00063    void *operator new(size_t size)  {  return mainmem.GetByteBlock(size);}
00064    void operator delete(void *ptr)  {}
00065 };
00066 
00067 struct DivSepComprInfo
00068    // Stores all the information about the subcompressors and delimiters
00069 {
00070    // If there is a separator at the beginning, we store it here
00071    char              *startseparator;
00072    unsigned long     startseparatorlen;
00073 
00074    DivCompressorItem *subcompressors;  // The list of subcompressors
00075 
00076    void CreateSubCompressors(char *paramstr,int len)
00077       // Generates the subcompressors from the parameter string
00078    {
00079       char *endstringptr;
00080       DivCompressorItem **curitemref;
00081 
00082       char  *ptr=paramstr;
00083       char  *endptr=paramstr+len;
00084 
00085       if(*ptr=='"')  // Did we find a separator string at the beginning ?
00086       {
00087          endstringptr=::ParseString(ptr,ptr+len);
00088 
00089          startseparator=ptr+1;
00090          startseparatorlen=endstringptr-ptr-1;
00091 
00092          ptr=endstringptr+1;
00093       }
00094       else  // Otherwise, we don't have any start separator
00095       {
00096          startseparator=NULL;
00097          startseparatorlen=0;
00098       }
00099 
00100       // We now parse the subcompressors and separator strings
00101 
00102       curitemref=&subcompressors;
00103       *curitemref=NULL;
00104       
00105       do
00106       {
00107          ptr=SkipWhiteSpaces(ptr,endptr);
00108          if(ptr==endptr)   // Did we reach the end?
00109             break;
00110 
00111          // First, we identify a compressor
00112 
00113          *curitemref=new DivCompressorItem();
00114 
00115 #ifdef XMILL
00116          (*curitemref)->usercompressor=compressman.CreateCompressorInstance(ptr,endptr);
00117 #endif
00118 #ifdef XDEMILL
00119          (*curitemref)->useruncompressor=compressman.CreateUncompressorInstance(ptr,endptr);
00120 #endif
00121 
00122          (*curitemref)->next=NULL;
00123 
00124          // Next, we identify a delimiter string
00125 
00126          ptr=SkipWhiteSpaces(ptr,endptr);
00127          if(ptr==endptr)   // Did we reach the end?
00128             break;
00129 
00130          // There must be string afterwards
00131          endstringptr=::ParseString(ptr,endptr);
00132 
00133          // Let's store the separator string
00134          (*curitemref)->afterseparator=ptr+1;
00135          (*curitemref)->afterseparatorlen=endstringptr-ptr-1;
00136 
00137          ptr=endstringptr+1;
00138 
00139          curitemref=&((*curitemref)->next);
00140          *curitemref=NULL;
00141       }
00142       while(1);
00143 
00144       if(*curitemref!=NULL)
00145       {
00146          (*curitemref)->afterseparator=NULL;
00147          (*curitemref)->afterseparatorlen=0;
00148       }
00149    }
00150 };
00151 
00152 //*************************************************************************
00153 
00154 // The 'seq' compressor
00155 
00156 class DivSepCompressorFactory;
00157 
00158 #ifdef XMILL
00159 
00160 class DivSepCompressor : public UserCompressor
00161 {
00162    friend DivSepCompressorFactory;
00163 protected:
00164 
00165    DivSepComprInfo info;   // The information about the subcompressors
00166 
00167 public:
00168    void ComputeProperties()
00169    {
00170       isrejecting=1;canoverlap=1;
00171       isfixedlen=1;
00172       datasize=0;
00173       contnum=0;
00174 
00175       DivCompressorItem *item=info.subcompressors;
00176       while(item!=NULL)
00177       {
00178          datasize+=item->usercompressor->GetUserDataSize();
00179          contnum+=item->usercompressor->GetUserContNum();
00180 
00181          if(item->usercompressor->CanOverlap()==0)
00182             canoverlap=0;
00183 
00184          // If one of the subcompressors is not fixed-length, then the entire
00185          // compressor is not fixed-length
00186          if(item->usercompressor->IsFixedLen()==0)
00187             isfixedlen=0;
00188 
00189          item=item->next;
00190       }
00191    }
00192 
00193    void CreateSubCompressors(char *paramstr,int len)
00194    {
00195       info.CreateSubCompressors(paramstr,len);
00196    }
00197 
00198    void InitCompress(CompressContainer *cont,char *dataptr)
00199       // Initializes the the compressors
00200    {
00201       DivCompressorItem *item=info.subcompressors;
00202 
00203       while(item!=NULL)
00204       {
00205          item->usercompressor->InitCompress(cont,dataptr);
00206          cont+=item->usercompressor->GetUserContNum();
00207          dataptr+=item->usercompressor->GetUserDataSize();
00208          item=item->next;
00209       }
00210    }
00211 
00212    char ParseString(char *str,unsigned len,char *dataptr)
00213    {
00214       char  *ptr1=str,
00215             *ptr2,*curptr,*endptr,*itemptr;
00216       DivCompressorItem *item;
00217       unsigned i;
00218 
00219       // Do we have a start separator ?
00220       if(info.startseparator!=NULL)
00221       {
00222          ptr1=str;
00223          ptr2=info.startseparator;
00224 
00225          // If the the entire string is shorter than the separator length,
00226          // the string can definitely not match
00227          if(len<info.startseparatorlen)
00228             return 0;
00229 
00230          // Let's check whether the strings are equal
00231          for(i=0;i<info.startseparatorlen;i++)
00232          {
00233             if(*ptr1!=*ptr2)
00234                return 0;
00235             ptr1++;
00236             ptr2++;
00237          }
00238          itemptr=ptr1;
00239       }
00240       else
00241          itemptr=str;
00242 
00243       item=info.subcompressors;
00244 
00245       // As long as we have more subcompressors, we continue parsing
00246       // If 'item->next' is NULL, then the subcompressor in 'item->usercompressor'
00247       // must match the *rest* of the string and this is done outside of the loop.
00248       while(item->next!=NULL)
00249       {
00250          curptr=itemptr;
00251          endptr=str+len-item->afterseparatorlen;   // The endptr is the end of the entire string
00252                                                    // minus the length of the separator string
00253 
00254          // We search for the separator
00255          while(curptr<endptr)
00256          {
00257             ptr1=curptr;
00258             ptr2=item->afterseparator;
00259 
00260             for(i=0;i<item->afterseparatorlen;i++)
00261             {
00262                if(*ptr1!=*ptr2)
00263                   break;
00264                ptr1++;
00265                ptr2++;
00266             }
00267             // We found the separator ?
00268             if(i==item->afterseparatorlen)
00269                break;
00270 
00271             curptr++;
00272          }
00273 
00274          if(curptr>=endptr)
00275             // We didn't find the separator ? => Exit
00276             return 0;
00277 
00278          // We keep the length of the string up to the delimiter
00279          // This will be used in 'CompressString' later.
00280          item->curitemlen=curptr-itemptr;
00281 
00282          // Let's see if the subcompressor can parse the string
00283          if(item->usercompressor->ParseString(itemptr,curptr-itemptr,dataptr)==0)
00284             return 0;
00285 
00286          dataptr+=item->usercompressor->GetUserDataSize();
00287 
00288          itemptr=ptr1;
00289          item=item->next;
00290       }
00291 
00292       endptr=str+len;
00293 
00294       // If we have a delimiter at the end, then we check whether it matches
00295       // the end of 'str'
00296       if(item->afterseparator!=NULL)
00297       {
00298          ptr1=endptr-item->afterseparatorlen;
00299          if(ptr1<itemptr)
00300             return 0;
00301          ptr2=item->afterseparator;
00302 
00303          for(i=0;i<item->afterseparatorlen;i++)
00304          {
00305             if(*ptr1!=*ptr2)  // Tail delimiter doesn't match?
00306                return 0;
00307             ptr1++;
00308             ptr2++;
00309          }
00310          endptr-=item->afterseparatorlen;
00311       }
00312 
00313       item->curitemlen=endptr-itemptr;
00314 
00315       // Let's do the parsing for the last subcompressor
00316       if(item->usercompressor->ParseString(itemptr,endptr-itemptr,dataptr)==0)
00317          return 0;
00318 
00319       return 1;
00320    }
00321 
00322    void CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr)
00323       // Compresses the given input string
00324       // 'dataptr' denotes the state
00325       // Since the compressor is 'rejecting', the function can expect
00326       // that 'ParseString' has been called before and
00327       // 'item->curitemlen' has been set for each subcompressor
00328    {
00329       DivCompressorItem *item=info.subcompressors;
00330       char              *startitemptr;
00331 
00332       // Skip the first separator
00333       startitemptr=str+info.startseparatorlen;
00334 
00335       while(item!=NULL)
00336       {
00337          // Compress using the next subcompressor and the length stored
00338          // in 'item->curitemlen'
00339          item->usercompressor->CompressString(startitemptr,item->curitemlen,cont,dataptr);
00340 
00341          cont+=item->usercompressor->GetUserContNum();
00342          dataptr+=item->usercompressor->GetUserDataSize();
00343 
00344          // Skip the next separator and go to the next 
00345          startitemptr+=item->curitemlen+item->afterseparatorlen;
00346          item=item->next;
00347       }
00348    }
00349 
00350    void FinishCompress(CompressContainer *cont,char *dataptr)
00351       // Finishes the compression - the compressor should write any
00352       // remaining data to the containers
00353       // For the seq-compressor, all subcompressors are 'finished'
00354    {
00355       DivCompressorItem *item=info.subcompressors;
00356 
00357       while(item!=NULL)
00358       {
00359          item->usercompressor->FinishCompress(cont,dataptr);
00360 
00361          cont+=item->usercompressor->GetUserContNum();
00362          dataptr+=item->usercompressor->GetUserDataSize();
00363 
00364          item=item->next;
00365       }
00366    }
00367 
00368    void PrintCompressInfo(char *dataptr,unsigned long *overalluncomprsize,unsigned long *overallcomprsize)
00369       // Prints statistical information about how well the compressor compressed
00370       // the data
00371    {
00372       DivCompressorItem *item=info.subcompressors;
00373 
00374       while(item!=NULL)
00375       {
00376          item->usercompressor->PrintCompressInfo(dataptr,overalluncomprsize,overallcomprsize);
00377 
00378          dataptr+=item->usercompressor->GetUserDataSize();
00379 
00380          item=item->next;
00381       }
00382    }
00383 };
00384 
00385 #endif // XMILL
00386 
00387 //************************************************************************
00388 //************************************************************************
00389 
00390 //** The Decompressor ********
00391 
00392 #ifdef XDEMILL
00393 
00394 class DivSepUncompressor : public UserUncompressor
00395 {
00396    friend DivSepCompressorFactory;
00397 protected:
00398 
00399    DivSepComprInfo info;
00400 
00401 public:
00402    void ComputeProperties()
00403       // Computes the properties of the decompressor
00404    {
00405       DivCompressorItem *item=info.subcompressors;
00406 
00407       datasize=0;
00408       contnum=0;
00409 
00410       while(item!=NULL)
00411       {
00412          datasize+=item->useruncompressor->GetUserDataSize();
00413          contnum+=item->useruncompressor->GetUserContNum();
00414          item=item->next;
00415       }
00416    }
00417 
00418    void CreateSubCompressors(char *paramstr,int len)
00419       // Creates the subcompressor structures based the
00420       // parameter string
00421    {
00422       info.CreateSubCompressors(paramstr,len);
00423    }
00424 
00425    void InitUncompress(UncompressContainer *cont,char *dataptr)
00426       // Initializes the subcompressors
00427    {
00428       DivCompressorItem *item=info.subcompressors;
00429 
00430       while(item!=NULL)
00431       {
00432          item->useruncompressor->InitUncompress(cont,dataptr);
00433          cont+=item->useruncompressor->GetUserContNum();
00434          dataptr+=item->useruncompressor->GetUserDataSize();
00435          item=item->next;
00436       }
00437    }
00438 
00439    void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *output)
00440       // Does the actual decompression of a single text item
00441       // and prints the text to 'output'
00442    {
00443       DivCompressorItem *item=info.subcompressors;
00444 
00445       // We output the start separator, if it exists
00446       if(info.startseparator!=NULL)
00447          output->characters(info.startseparator,info.startseparatorlen);
00448 
00449       // Each decompressor decompresses its own piece of text
00450       // from the corresponding containers
00451       while(item!=NULL)
00452       {
00453          item->useruncompressor->UncompressItem(cont,dataptr,output);
00454 
00455          if(item->afterseparator!=NULL)
00456             output->characters(item->afterseparator,item->afterseparatorlen);
00457 
00458          cont+=item->useruncompressor->GetUserContNum();
00459          dataptr+=item->useruncompressor->GetUserDataSize();
00460 
00461          item=item->next;
00462       }
00463    }
00464 
00465    void FinishUncompress(UncompressContainer *cont,char *dataptr)
00466       // Finishes the decompression
00467    {
00468       DivCompressorItem *item=info.subcompressors;
00469 
00470       while(item!=NULL)
00471       {
00472          item->useruncompressor->FinishUncompress(cont,dataptr);
00473 
00474          cont+=item->useruncompressor->GetUserContNum();
00475          dataptr+=item->useruncompressor->GetUserDataSize();
00476 
00477          item=item->next;
00478       }
00479    }
00480 };
00481 
00482 #endif
00483 
00484 //****************************************************************************
00485 
00486 class DivSepCompressorFactory : public UserCompressorFactory
00487    // The compressor factory for 'seq'
00488 {
00489 public:
00490    char *GetName()         {  return "seq"; }
00491    char *GetDescription()  {  return "Sequence compressor for strings with separators"; }
00492 
00493 #ifdef XMILL
00494    UserCompressor *InstantiateCompressor(char *paramstr,int len)
00495       // Instantiates the compressor
00496    {
00497       if(paramstr==NULL)
00498       {
00499          Error("Sequence compressor 'seq' must have a sequence of strings and compressors as parameters");
00500          Exit();
00501       }
00502 
00503       DivSepCompressor  *divsepcompressor=new DivSepCompressor();
00504 
00505       // We initialize the compressor
00506       divsepcompressor->CreateSubCompressors(paramstr,len);
00507       divsepcompressor->ComputeProperties();
00508       return divsepcompressor;
00509    }
00510 #endif
00511 
00512 #ifdef XDEMILL
00513    UserUncompressor *InstantiateUncompressor(char *paramstr,int len)
00514       // Instantiates the decompressor
00515    {
00516       DivSepUncompressor  *divsepuncompressor=new DivSepUncompressor();
00517 
00518       // Intializes the decompressor
00519       divsepuncompressor->CreateSubCompressors(paramstr,len);
00520       divsepuncompressor->ComputeProperties();
00521       return divsepuncompressor;
00522    }
00523 #endif
00524 };
00525 
00526 // The actual compressor factory for the combined sequence compressor
00527 DivSepCompressorFactory  divsepcompressfactory;
00528 
00529 
00530 //******************************************************************************
00531 //******************************************************************************
00532 //******************************************************************************
00533 //******************************************************************************
00534 //******************************************************************************
00535 //******************************************************************************
00536 
00537 // The DivCombine compressor is similar to the DivSep compressor.
00538 // The only difference is that the containers of the subcompressors 'overlap' -
00539 // i.e. the overall number of containers of the 'seqcomb' compressor is
00540 // the *maximum* number of containers of the subcompressors.
00541 
00542 #ifdef XMILL
00543 
00544 class DivCombineCompressor : public DivSepCompressor
00545    // The compressor class is inherited from DivSepCompressor so that
00546    // we can use 'ParseString'
00547 {
00548    friend DivSepCompressorFactory;
00549 
00550 public:
00551    void ComputeProperties()
00552    {
00553       isrejecting=1;canoverlap=1;
00554       isfixedlen=1;
00555       datasize=0;
00556       contnum=0;
00557       
00558       DivCompressorItem *item=info.subcompressors;
00559       while(item!=NULL)
00560       {
00561          datasize+=item->usercompressor->GetUserDataSize();
00562 
00563          // We find the maximum container number
00564          if(contnum<item->usercompressor->GetUserContNum())
00565             contnum=item->usercompressor->GetUserContNum();
00566 
00567          if(item->usercompressor->CanOverlap()==0)
00568             canoverlap=0;
00569 
00570          if(item->usercompressor->IsFixedLen()==0)
00571             isfixedlen=0;
00572 
00573          item=item->next;
00574       }
00575    }
00576 
00577    void CreateSubCompressors(char *paramstr,int len)
00578    {
00579       info.CreateSubCompressors(paramstr,len);
00580    }
00581 
00582    void InitCompress(CompressContainer *cont,char *dataptr)
00583    {
00584       DivCompressorItem *item=info.subcompressors;
00585 
00586       while(item!=NULL)
00587       {
00588          // Note that 'cont' is the same for all subcompressors.
00589          item->usercompressor->InitCompress(cont,dataptr);
00590          dataptr+=item->usercompressor->GetUserDataSize();
00591          item=item->next;
00592       }
00593    }
00594 
00595    void CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr)
00596        // Compresses the given input string
00597       // 'dataptr' denotes the state
00598       // Since the compressor is 'rejecting', the function can expect
00599       // that 'DivSepCompressor::ParseString' has been called before and
00600       // 'item->curitemlen' has been set for each subcompressor
00601    {
00602       DivCompressorItem *item=info.subcompressors;
00603       char              *startitemptr;
00604 
00605       startitemptr=str+info.startseparatorlen;
00606 
00607       while(item!=NULL)
00608       {
00609          item->usercompressor->CompressString(startitemptr,item->curitemlen,cont,dataptr);
00610          dataptr+=item->usercompressor->GetUserDataSize();
00611 
00612          startitemptr+=item->curitemlen+item->afterseparatorlen;
00613          item=item->next;
00614       }
00615    }
00616 
00617    void FinishCompress(CompressContainer *cont,char *dataptr)
00618       // Finishes the compression - the compressor should write any
00619       // remaining data to the containers
00620    {
00621       DivCompressorItem *item=info.subcompressors;
00622 
00623       while(item!=NULL)
00624       {
00625          item->usercompressor->FinishCompress(cont,dataptr);
00626          dataptr+=item->usercompressor->GetUserDataSize();
00627          item=item->next;
00628       }
00629    }
00630 
00631    void PrintCompressInfo(char *dataptr,unsigned long *overalluncomprsize,unsigned long *overallcomprsize)
00632       // Prints statistical information about how well the compressor compressed
00633       // the data
00634    {
00635       DivCompressorItem *item=info.subcompressors;
00636 
00637       while(item!=NULL)
00638       {
00639          item->usercompressor->PrintCompressInfo(dataptr,overalluncomprsize,overallcomprsize);
00640 
00641          dataptr+=item->usercompressor->GetUserDataSize();
00642 
00643          item=item->next;
00644       }
00645    }
00646 };
00647 
00648 #endif
00649 
00650 //**********************************************************************************
00651 
00652 // The combined sequence decompressor
00653 
00654 #ifdef XDEMILL
00655 
00656 class DivCombineUncompressor : public DivSepUncompressor
00657    // Note that the class is denoted from 'DivSepUncompressor' so that
00658    // we can use the 'info' attribute
00659 {
00660    friend DivSepCompressorFactory;
00661 
00662 public:
00663    void ComputeProperties()
00664       // Computes the properties of the decompressor
00665       // Note that this is different from 'ComputeProperties' in the original
00666       // DivSepUncompressor
00667    {
00668       DivCompressorItem *item=info.subcompressors;
00669 
00670       datasize=0;
00671       contnum=0;
00672 
00673       while(item!=NULL)
00674       {
00675          datasize+=item->useruncompressor->GetUserDataSize();
00676 
00677          // We find the maximum container count:
00678          if(contnum<item->useruncompressor->GetUserContNum())
00679             contnum=item->useruncompressor->GetUserContNum();
00680          item=item->next;
00681       }
00682    }
00683 
00684    void CreateSubCompressors(char *paramstr,int len)
00685    {
00686       info.CreateSubCompressors(paramstr,len);
00687    }
00688 
00689    void InitUncompress(UncompressContainer *cont,char *dataptr)
00690       // Initializes the decompressor
00691    {
00692       DivCompressorItem *item=info.subcompressors;
00693 
00694       while(item!=NULL)
00695       {
00696          item->useruncompressor->InitUncompress(cont,dataptr);
00697 
00698          dataptr+=item->useruncompressor->GetUserDataSize();
00699          item=item->next;
00700       }
00701    }
00702 
00703    void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *output)
00704       // Does the actual decompression of a single text item
00705       // and prints the text to 'output'
00706    {
00707       DivCompressorItem *item=info.subcompressors;
00708 
00709       if(info.startseparator!=NULL)
00710          output->characters(info.startseparator,info.startseparatorlen);
00711 
00712       while(item!=NULL)
00713       {
00714          item->useruncompressor->UncompressItem(cont,dataptr,output);
00715          if(item->afterseparator!=NULL)
00716             output->characters(item->afterseparator,item->afterseparatorlen);
00717          dataptr+=item->useruncompressor->GetUserDataSize();
00718 
00719          item=item->next;
00720       }
00721    }
00722 
00723    void FinishUncompress(UncompressContainer *cont,char *dataptr)
00724       // Finished the decompression
00725    {
00726       DivCompressorItem *item=info.subcompressors;
00727 
00728       while(item!=NULL)
00729       {
00730          item->useruncompressor->FinishUncompress(cont,dataptr);
00731          dataptr+=item->useruncompressor->GetUserDataSize();
00732          item=item->next;
00733       }
00734    }
00735 };
00736 
00737 #endif
00738 
00739 //**********************************************************************************
00740 
00741 class DivCombineCompressorFactory : public DivSepCompressorFactory
00742    // The compressor factory for combined compressor/decompressor
00743 {
00744 public:
00745    char *GetName()         {  return "seqcomb"; }
00746    char *GetDescription()  {  return "Combined sequence compressor for strings with separators"; }
00747 
00748 #ifdef XMILL
00749    UserCompressor *InstantiateCompressor(char *paramstr,int len)
00750    {
00751       if(paramstr==NULL)
00752       {
00753          Error("Combined sequence compressor 'seqcomb' must have a sequence of strings and compressors as parameters");
00754          Exit();
00755       }
00756 
00757       DivCombineCompressor  *divcombcompressor=new DivCombineCompressor();
00758 
00759       // Initializes the decompressor with the subcompressors
00760       divcombcompressor->CreateSubCompressors(paramstr,len);
00761       divcombcompressor->ComputeProperties();
00762       return divcombcompressor;
00763    }
00764 #endif
00765 
00766 #ifdef XDEMILL
00767    UserUncompressor *InstantiateUncompressor(char *paramstr,int len)
00768    {
00769       DivCombineUncompressor  *divcombuncompressor=new DivCombineUncompressor();
00770 
00771       // Initializes the decompressor with the subcompressors
00772       divcombuncompressor->CreateSubCompressors(paramstr,len);
00773       divcombuncompressor->ComputeProperties();
00774       return divcombuncompressor;
00775    }
00776 #endif
00777 };
00778 
00779 // The actual compressor factory for the combined sequence compressor
00780 DivCombineCompressorFactory  divcombcompressfactory;

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