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

OrCompress.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 Or-Compressor.
00032 // The Or-compressor has name 'or' and a list of other compressors as parameters
00033 
00034 #include "CompressMan.hpp"
00035 
00036 #ifdef XDEMILL
00037 #include "UnCompCont.hpp"
00038 #endif
00039 
00040 struct OrCompressorItem
00041    // Each parameter of the or-compressor is stored in this structur
00042 {
00043    OrCompressorItem  *next;   // Next parameter
00044 #ifdef XMILL
00045    UserCompressor    *usercompressor;
00046 #endif
00047 #ifdef XDEMILL
00048    UserUncompressor  *useruncompressor;
00049 #endif
00050 
00051    void *operator new(size_t size)  {  return mainmem.GetByteBlock(size);}
00052    void operator delete(void *ptr)  {}
00053 };
00054 
00055 //*************************
00056 
00057 // Until now, we only implemented the separate Or-compressor
00058 // - i.e. each sub-compressor gets own containers and there
00059 // is no overlapping between containers
00060 
00061 class OrSepCompressorFactory;
00062 
00063 struct OrSepCompressorInfo
00064 {
00065    OrCompressorItem  *subcompressors;
00066 
00067    void CreateSubCompressors(char *paramstr,int len)
00068       // Parses a given parameter string and creates the structure of
00069       // sub-compressor parameters
00070    {
00071       OrCompressorItem **curitemref;
00072 
00073       char  *ptr=paramstr;
00074       char  *endptr=paramstr+len;
00075 
00076       subcompressors=NULL;
00077 
00078       curitemref=&subcompressors;
00079       
00080       while(ptr<endptr)
00081       {
00082          if((*ptr==' ')||(*ptr==',')||(*ptr=='\t')||(*ptr=='\r')||(*ptr=='\n'))
00083          {
00084             ptr++;
00085             continue;
00086          }
00087 
00088          *curitemref=new OrCompressorItem();
00089 
00090          // For compression, we create compressors
00091          // For decompression, we create decompressors
00092 #ifdef XMILL
00093          (*curitemref)->usercompressor=compressman.CreateCompressorInstance(ptr,endptr);
00094 #endif
00095 #ifdef XDEMILL
00096          (*curitemref)->useruncompressor=compressman.CreateUncompressorInstance(ptr,endptr);
00097 #endif
00098          // Pointer 'ptr' is moved forward by the previous functions
00099 
00100          (*curitemref)->next=NULL;
00101 
00102          curitemref=&((*curitemref)->next);
00103       }
00104    }
00105 };
00106 
00107 //**************************************************************************************
00108 
00109 #ifdef XMILL
00110 
00111 class OrSepCompressor : public UserCompressor
00112    // The compressor part of the Or-compressor,
00113 {
00114    friend OrSepCompressorFactory;
00115 protected:
00116 
00117    OrSepCompressorInfo  info; // The parameters
00118 
00119    long                 curidx;           // This is used
00120    OrCompressorItem     *curcompressor;
00121 
00122    unsigned short       curdataoffset;
00123    unsigned short       curcontoffset;
00124 
00125 public:
00126 
00127    void ComputeProperties()
00128       // We determine whether the or-compressor is rejecting or can be overlapping
00129       // Furthermore, we determine the number of containers and the user data size needed
00130    {
00131       datasize=0;
00132       contnum=1;     // We need one container for ourselves
00133       isrejecting=1;
00134       canoverlap=1;
00135       isfixedlen=0;
00136 
00137       OrCompressorItem *item=info.subcompressors;
00138       while(item!=NULL)
00139       {
00140          if(item->usercompressor->IsRejecting()==0)
00141             isrejecting=0;
00142 
00143          if(item->usercompressor->CanOverlap()==0)
00144             canoverlap=0;
00145 
00146          contnum+=item->usercompressor->GetUserContNum();
00147          datasize+=item->usercompressor->GetUserDataSize();
00148          item=item->next;
00149       }
00150    }
00151 
00152    void InitCompress(CompressContainer *cont,char *dataptr)
00153       // Before we start any compression, we initialize the compressor.
00154       // 'dataptr' denotes the state
00155    {
00156       OrCompressorItem *item=info.subcompressors;
00157 
00158       curidx=-1;
00159 
00160       cont++;
00161 
00162       while(item!=NULL)
00163       {
00164          item->usercompressor->InitCompress(cont,dataptr);
00165 
00166          cont+=item->usercompressor->GetUserContNum();
00167          dataptr+=item->usercompressor->GetUserDataSize();
00168          item=item->next;
00169       }
00170    }
00171 
00172    char ParseString(char *str,unsigned len,char *dataptr)
00173       // Parses the string and returns 1, if accepted, otherwise 0.
00174       // This function does not actually store/compreess the string
00175       // But it can keep an internal state - in the next step,
00176       // CompressString is called.
00177    {
00178       char  *ptr1=str;
00179       OrCompressorItem *item;
00180 
00181       item=info.subcompressors;
00182 
00183       curidx=0;
00184       curdataoffset=0;
00185       curcontoffset=1;
00186 
00187       while(item!=NULL)
00188       {
00189          if(item->usercompressor->ParseString(str,len,dataptr))
00190             break;
00191 
00192          dataptr+=item->usercompressor->GetUserDataSize();
00193 
00194          curidx++;
00195          curdataoffset+=item->usercompressor->GetUserDataSize();
00196          curcontoffset+=item->usercompressor->GetUserContNum();
00197 
00198          item=item->next;
00199       }
00200 
00201       if(item==NULL) // None of the subcompressors accepted the text ?
00202          return 0;
00203 
00204       curcompressor=item;
00205 
00206       return 1;
00207    }
00208 
00209    void CompressString(char *str,unsigned len,CompressContainer *cont,char *dataptr)
00210       // Compresses the given input string
00211       // 'dataptr' denotes the state
00212       // If the compressor is 'rejecting', then the function can expect
00213       // that 'ParseString' has been called before.
00214    {
00215       if(curidx==-1)
00216          ParseString(str,len,dataptr);
00217 
00218       cont->StoreUInt32(curidx);
00219 
00220       cont+=curcontoffset;
00221       dataptr+=curdataoffset;
00222 
00223       curidx=-1;
00224 
00225       curcompressor->usercompressor->CompressString(str,len,cont,dataptr);
00226    }
00227 
00228    void FinishCompress(CompressContainer *cont,char *dataptr)
00229       // Finishes the compression - the compressor should write any
00230       // remaining data to the containers
00231    {
00232       OrCompressorItem *item=info.subcompressors;
00233 
00234       cont++;
00235 
00236       while(item!=NULL)
00237       {
00238          item->usercompressor->FinishCompress(cont,dataptr);
00239 
00240          cont+=item->usercompressor->GetUserContNum();
00241          dataptr+=item->usercompressor->GetUserDataSize();
00242          item=item->next;
00243       }
00244    }
00245 
00246    void PrintCompressInfo(char *dataptr,unsigned long *overalluncomprsize,unsigned long *overallcomprsize)
00247       // Prints statistical information about how well the compressor compressed
00248       // the data
00249    {
00250       OrCompressorItem *item=info.subcompressors;
00251 
00252       while(item!=NULL)
00253       {
00254          item->usercompressor->PrintCompressInfo(dataptr,overalluncomprsize,overallcomprsize);
00255 
00256          dataptr+=item->usercompressor->GetUserDataSize();
00257          item=item->next;
00258       }
00259    }
00260 
00261 };
00262 
00263 #endif // XMILL
00264 
00265 //**********************************************************************************
00266 //**********************************************************************************
00267 
00268 // The decompressor for the separated Or-compressor
00269 
00270 #ifdef XDEMILL
00271 
00272 class OrSepUncompressor : public UserUncompressor
00273 {
00274    friend OrSepCompressorFactory;
00275    OrSepCompressorInfo  info;
00276 
00277    void ComputeProperties()
00278       // Computes the properties. Determines the number of containers
00279       // and the size of the user data
00280    {
00281       datasize=0;
00282       contnum=1;  // We need one container for ourselves
00283 
00284       OrCompressorItem *item=info.subcompressors;
00285       while(item!=NULL)
00286       {
00287          contnum+=item->useruncompressor->GetUserContNum();
00288          datasize+=item->useruncompressor->GetUserDataSize();
00289          item=item->next;
00290       }
00291    }
00292 
00293    void InitUncompress(UncompressContainer *cont,char *dataptr)
00294       // Initialized the decompressor
00295       // Each subcompressor is called with the corresponding containers and state
00296    {
00297       OrCompressorItem *item=info.subcompressors;
00298 
00299       cont++;
00300 
00301       while(item!=NULL)
00302       {
00303          item->useruncompressor->InitUncompress(cont,dataptr);
00304 
00305          cont+=item->useruncompressor->GetUserContNum();
00306          dataptr+=item->useruncompressor->GetUserDataSize();
00307          item=item->next;
00308       }
00309    }
00310 
00311    void UncompressItem(UncompressContainer *cont,char *dataptr,XMLOutput *output)
00312       // Does the actual decompression of a single text item
00313       // and prints the text to 'output'
00314    {
00315       // We load the tag that determined which sub-compressor was used.
00316       unsigned long subcompressidx=cont->LoadUInt32();
00317       OrCompressorItem  *item=info.subcompressors;
00318 
00319       cont++;
00320 
00321       // We skip over the containers and state spaces of all previous
00322       // containers
00323       while(subcompressidx--)
00324       {
00325          cont+=item->useruncompressor->GetUserContNum();
00326          dataptr+=item->useruncompressor->GetUserDataSize();
00327          item=item->next;
00328       }
00329       // Then we do the decompression
00330       item->useruncompressor->UncompressItem(cont,dataptr,output);
00331    }
00332 };
00333 
00334 #endif
00335 
00336 //**********************************************************************************
00337 //**********************************************************************************
00338 
00339 // The Compressor Factory for the separate Or-compressor
00340 class OrSepCompressorFactory : public UserCompressorFactory
00341 {
00342 public:
00343    char *GetName()         {  return "or"; }
00344    char *GetDescription()  {  return "Variant compressor"; }
00345 
00346 #ifdef XMILL
00347    UserCompressor *InstantiateCompressor(char *paramstr,int len)
00348       // Instantiates the Or-compressor for specific parameters
00349    {
00350       if(paramstr==NULL)
00351       {
00352          Error("Division compressor 'divsep' requires a sequence of strings and compressors as parameters");
00353          Exit();
00354       }
00355 
00356       // Let's create the Or-compressor and parse the parameters
00357       OrSepCompressor  *orsepcompressor=new OrSepCompressor();
00358 
00359       orsepcompressor->info.CreateSubCompressors(paramstr,len);
00360       orsepcompressor->ComputeProperties();
00361 
00362       return orsepcompressor;
00363    }
00364 #endif
00365 
00366 #ifdef XDEMILL
00367    UserUncompressor *InstantiateUncompressor(char *paramstr,int len)
00368       // Instantiates the Or-decompressor for specific parameters
00369    {
00370       // Let's create the Or-decompressor and parse the parameters
00371       // Note that the parameters *must* be correct.
00372       OrSepUncompressor  *orsepuncompressor=new OrSepUncompressor();
00373 
00374       orsepuncompressor->info.CreateSubCompressors(paramstr,len);
00375       orsepuncompressor->ComputeProperties();
00376 
00377       return orsepuncompressor;
00378    }
00379 #endif
00380 };
00381 
00382 // The actual Or-compressor factory
00383 OrSepCompressorFactory  orsepcompressfactory;
00384 
00385 //**********************************************************************************
00386 //**********************************************************************************
00387 //**********************************************************************************
00388 //**********************************************************************************

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