Octane v1.01.20 - The Open Compression Toolkit for C++ http://octane.sourceforge.net/
Homepage | Main | Modules | Class Hierarchy | Compound List | File List | Compound Members | Related Pages

compressors/compressor_statistical.cpp

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 //---------------------------------------------------------------------------
00013 
00014 //---------------------------------------------------------------------------
00015 // application includes
00016 #include "compressor_statistical.hpp"
00017 // system includes
00018 using namespace std;
00019 //---------------------------------------------------------------------------
00020 
00021 
00022 //---------------------------------------------------------------------------
00023 // Normally we would create a global instance in order to register it
00024 //  automatically with the global manager, BUT for this base class we don't
00025 //  want to since its not a real available compressor.  But you will want to
00026 //  create one for any derived class that is useable.
00027 // OctaneCompressor_Statistical GloballyInstantiated_OctaneCompressor_Statistical;
00028 //---------------------------------------------------------------------------
00029 
00030 
00031 //---------------------------------------------------------------------------
00032 OctaneCompressor_Statistical::OctaneCompressor_Statistical(bool registerme)
00033         :OctaneCompressor(registerme)
00034 {
00035         // create the children objects
00036         parserp=NULL;
00037         modelerp=NULL;
00038         coderp=NULL;
00039         // in a derived class you would create real parsers,modelers, and coders here.
00040 
00041         // REGISTER WITH COMPRESSOR MANAGER
00042         //  this use a trick to make sure the global manager is ready for registration
00043         //  and at the same time automatically register this instance with the global manager
00044         //  note that the insurer is just temporary, and deletes when we exit the procedure
00045         // BUT for this base class we don't want to since its not a real available
00046         //  compressor.  But you will want to create one for any derived class that is useable.
00047         // CompressorManager_SingletonInsurer managerinsurance(this);
00048 }
00049 
00050 OctaneCompressor_Statistical::~OctaneCompressor_Statistical()
00051 {
00052         // destructor
00053         // delete children objects
00054         if (coderp!=NULL)
00055                 delete coderp;
00056         if (modelerp!=NULL)
00057                 delete modelerp;
00058         if (parserp!=NULL)
00059                 delete parserp;
00060 }
00061 //---------------------------------------------------------------------------
00062 
00063 
00064 
00065 
00066 //---------------------------------------------------------------------------
00067 // OCTANE PUBLIC API - RTTI FUNCTIONS - these are supported by all derived classes
00068 
00069 string OctaneCompressor_Statistical::GetHelpInformation()
00070 {
00071         // show help info from our parser,model,coder
00072         string helpinfo;
00073 
00074         // generic help information for children
00075         helpinfo += PrefixNonEmptyString("Parser Help:\n-------------------------\n",parserp->GetHelpInformation());
00076         helpinfo += PrefixNonEmptyString("Modeler Help:\n-------------------------\n",modelerp->GetHelpInformation());
00077         helpinfo += PrefixNonEmptyString("Coder Help:\n-------------------------\n",coderp->GetHelpInformation());
00078 
00079         // return amalgamated string
00080         return helpinfo;
00081 }
00082 //---------------------------------------------------------------------------
00083 
00084 
00085 
00086 //---------------------------------------------------------------------------
00087 // OCTANE PUBLIC API - AUXILIARY FUNCTIONS - these are supported by all derived classes
00088 
00089 void OctaneCompressor_Statistical::ShowDebuggingInfo()
00090 {
00091         // generic debugging info for children
00092         parserp->ShowDebuggingInfo();
00093         modelerp->ShowDebuggingInfo();
00094         coderp->ShowDebuggingInfo();
00095 }
00096 
00097 unsigned int OctaneCompressor_Statistical::GetMemoryUsed()
00098 {
00099         // return the size of us and all our children
00100         return (unsigned int)(sizeof(this)+parserp->GetMemoryUsed()+modelerp->GetMemoryUsed()+coderp->GetMemoryUsed());
00101 }
00102 
00103 unsigned int OctaneCompressor_Statistical::GetDiskspaceUsed(bool fortempdecompressiononly)
00104 {
00105         // return use of disk space used to save our state and state of children
00106         return (parserp->GetDiskspaceUsed(fortempdecompressiononly)+modelerp->GetDiskspaceUsed(fortempdecompressiononly)+coderp->GetDiskspaceUsed(fortempdecompressiononly));
00107 }
00108 
00109 std::string OctaneCompressor_Statistical::GetParametersInformation()
00110 {
00111         // optional parameter management; return true on success
00112         string parameterinfo;
00113 
00114         // generic parameter information for children
00115         parameterinfo += PrefixNonEmptyString("Parser Parameters:\n-------------------------\n",parserp->GetParametersInformation());
00116         parameterinfo += PrefixNonEmptyString("Modeler Parameters:\n-------------------------\n",modelerp->GetParametersInformation());
00117         parameterinfo += PrefixNonEmptyString("Coder Parameters:\n-------------------------\n",coderp->GetParametersInformation());
00118 
00119         // return amalgamated string
00120         return parameterinfo;
00121 }
00122 
00123 void OctaneCompressor_Statistical::SetDefaultParameters()
00124 {
00125         // set default parameters for children
00126         parserp->SetDefaultParameters();
00127         modelerp->SetDefaultParameters();
00128         coderp->SetDefaultParameters();
00129 }
00130 
00131 bool OctaneCompressor_Statistical::SetParameter(const std::string &parametername,const std::string &parametervalue)
00132 {
00135         bool bretv;
00136         
00137         bretv=parserp->SetParameter(parametername,parametervalue);
00138         if (!bretv)
00139                 bretv=modelerp->SetParameter(parametername,parametervalue);
00140         if (!bretv)
00141                 bretv=coderp->SetParameter(parametername,parametervalue);
00142         return bretv;
00143 }
00144 
00145 bool OctaneCompressor_Statistical::DoProtectedSaveState(bitwriter &to,bool fortempdecompressiononly)
00146 {
00147         // save state; returns true on success
00148         bool bretv;
00149         bretv=parserp->SaveState(to,fortempdecompressiononly);
00150         if (bretv)
00151                 bretv=modelerp->SaveState(to,fortempdecompressiononly);
00152         if (bretv)
00153                 bretv=coderp->SaveState(to,fortempdecompressiononly);
00154         return bretv;
00155 }
00156 
00157 bool OctaneCompressor_Statistical::DoProtectedLoadState(bitreader &from)
00158 {
00159         // save state; returns true on success
00160         bool bretv;
00161         bretv=parserp->LoadState(from);
00162         if (bretv)
00163                 bretv=modelerp->LoadState(from);
00164         if (bretv)
00165                 {
00166                 bretv=coderp->LoadState(from);
00168                 coderp->ReceiveNotification_ModelChange_AllSymbolWeights(modelerp);
00169                 }
00170         return bretv;
00171 }
00172 //---------------------------------------------------------------------------
00173 
00174 
00175 
00176 //---------------------------------------------------------------------------
00177 // COMPRESSOR PUBLIC API - PREPARATION FOR COMPRESSING/DECOMPRESSING
00178 void OctaneCompressor_Statistical::ResetState()
00179 {
00180         // reset the state of the parser with any default starting symbols, can be called multiple times; returns true on success
00181         parserp->ResetState();
00182         modelerp->ResetState();
00183         coderp->ResetState();
00184 }
00185 
00186 
00187 void OctaneCompressor_Statistical::SetupAnyDefaultParser()
00188 {
00189         // if a parser starts out ready to parse, we might need to build a model/coder from it
00190         if (parserp->IsReadyToParse())
00191                 {
00192                 modelerp->CreateModelUsingParser(parserp);
00193                 if (modelerp->IsReadyToModel())
00194                         {
00196                         coderp->ReceiveNotification_ModelChange_AllSymbolWeights(modelerp);
00197                         }
00198                 }
00199 }
00200 
00201 
00202 bool OctaneCompressor_Statistical::DoProtectedCreateSymbolsAndModelsUsingStream(bitreader &from)
00203 {
00204         // optionally (pre)process an input stream to update/create a symbol set from it; returns true on success
00205         bool bretv;
00206         // build parser symbol set using stream
00207         // HOWEVER this can be a bit tricky, because we have 2 structures (parser and modeler) which may want to process from stream
00208         //  so we need to rewind it after the parser gets done with it.
00209         
00210         // record starting position of from stream (probably 0)
00211         size_t fromstartpos=from.tell_bit();
00212         
00213         // give it to parser
00214         bretv = parserp->CreateSymbolSetUsingStream(from);
00215         // now build the model using the symbols created by the parser, and again on the stream from
00216         if (bretv)
00217                 {
00218                 // reset from stream to start
00219                 from.seek_bit(fromstartpos);
00220                 // now have model process it
00221                 bretv = modelerp->CreateModelUsingStream(parserp,from);
00222                 if (bretv)
00223                         {
00225                         coderp->ReceiveNotification_ModelChange_AllSymbolWeights(modelerp);
00226                         }
00227                 }
00228 
00229         // return success
00230         return bretv;
00231 }
00232 
00233 bool OctaneCompressor_Statistical::PrepareForCompression()
00234 {
00235         // prepare for parsing mode, must be called after zero or more Updating calls, and before parsing begins; returns true on success
00236         bool bretv;
00237         
00238         // first prepare the parser (this should ensure we have a valid symbol set)
00239         bretv=parserp->PrepareForParsing();
00240         // now prepare the model (give it parser info in case it wants it)
00241         if (bretv)
00242                 modelerp->PrepareForModeling(parserp);
00243         // now build coder based on modeler
00244         if (bretv)
00245                 coderp->PrepareForCoding(modelerp);
00246 
00247         // return success
00248         return bretv;
00249 }
00250 
00251 bool OctaneCompressor_Statistical::IsReadyToCompress()
00252 {
00253         // is the compressor ready to compress? Normally this is false until a dictionary is built or loaded.
00254         bool bretv1,bretv2,bretv3;
00255         
00256         if (!(bretv1=parserp->IsReadyToParse()))
00257                 cout << "the parser is not ready."<<endl;
00258         if (!(bretv2=modelerp->IsReadyToModel()))
00259                 cout << "the modeler is not ready."<<endl;
00260         if (!(bretv3=coderp->IsReadyToCode()))
00261                 cout << "the coder is not ready."<<endl;
00262         return (bretv1 && bretv2 && bretv3);
00263 }
00264 
00265 void OctaneCompressor_Statistical::SynchronizeStateForNewStream()
00266 {
00267         // synchronize state for a new stream - this *MUST* be called before beginning a new parsing stream
00268         // we just synchronize our components
00269         parserp->SynchronizeStateForNewStream();
00270         modelerp->SynchronizeStateForNewStream();
00271         coderp->SynchronizeStateForNewStream();
00272 }
00273 //---------------------------------------------------------------------------
00274 
00275 
00276 
00277 //---------------------------------------------------------------------------
00278 // COMPRESSOR PUBLIC API - COMPRESSING/DECOMPRESSING
00279 
00280 bool OctaneCompressor_Statistical::DoProtectedCompress(bitreader &from, bitwriter &to)
00281 {
00282         // compress all of from and send to to
00283         // ATTN: the only thing slightly troubling about this otherwise elegant routine, is the
00284         //  fact that there is no way for the components to change the symbol set during compression
00285         bool bretv=true;
00286         int symbolnumber;
00287 
00288         // we *must* inform our components that we are about to compress or decompress a new stream
00289         SynchronizeStateForNewStream();
00290 
00291         // loop parsing a symbol from parser until we hit end (note the last symbol will be an End-Of-Stream)
00292         while (parserp->ParseNextSymbolFromInput(from,symbolnumber))
00293                 {
00294                 // debug show some info?
00295                 //   cout << "$READ SYMBOL "<<symbolnumber<<": '"<<parserp->LookupSymbolText(symbolnumber)<<"'."<<endl;
00296                 // code the symbol given current model and codes
00297                 if (!(bretv=coderp->WriteSymbolBits(symbolnumber,to)))
00298                         break;
00299                 // now update the model based on this symbol (pass coderp so it can inform it if probabilities change).
00300                 // note that for four zero-order model this doesn't do anything, but we call it for completeness.
00301                 if (!(bretv=modelerp->UpdateModelAfterReceivingSymbol(symbolnumber,coderp)))
00302                         break;
00303                 }
00304 
00305         // when we finish coding a stream we want to align to byte boundary in the output
00306         //  this will happen automatically if we close the output stream now, but we do it manually in case we want to pack multiple
00307         //  input streams into the same output.
00308         coderp->AlignOutputStreamToByteBoundry(to);
00309 
00310         // return success
00311         return bretv;
00312 }
00313 
00314 bool OctaneCompressor_Statistical::DoProtectedDecompress(bitreader &from, bitwriter &to)
00315 {
00316         // decompress all of from and send to to
00317         // ATTN: the only thing slightly troubling about this otherwise elegant routine, is the
00318         //  fact that there is no way for the components to change the symbol set during compression
00319         bool bretv=true;
00320         int symbolnumber;
00321         bool isendofstreamsymbol;
00322 
00323         // we *must* inform our components that we are about to compress or decompress a new stream
00324         SynchronizeStateForNewStream();
00325         
00326         // loop decoding a symbol from coder until we hit end
00327         while (coderp->DecodeSymbolFromInput(symbolnumber,from))
00328                 {
00329                 // debug show some info?
00330                 //    cout << "$DECODED SYMBOL "<<symbolnumber<<": '"<<parserp->LookupSymbolText(symbolnumber)<<"'."<<endl;
00331                 // deParse the symbol given current model and symbol set
00332                 if (!(bretv=parserp->WriteSymbolText(to,symbolnumber,isendofstreamsymbol)))
00333                         break;
00334                 // did we just parse an EOS(end-of-stream) symbol? if so we need to align input to byte boundary (normally its end of file)
00335                 if (isendofstreamsymbol)
00336                         {
00337                         // when we finish coding a stream we want to align to byte boundary in the output
00338                         //  this will happen automatically if we close the output stream now, but we do it manually in case we want to pack multiple
00339                         //  input streams into the same output. note that this we will almost always be leaving this loop after this symbol.
00340                         coderp->AlignInputStreamToByteBoundry(from);
00341                         // cout << "$DEBUG aligning input."<<endl;
00342                         }
00343                 // now update the model based on this symbol (pass coderp so it can inform it if probabilities change).
00344                 // note that for four zero-order model this doesn't do anything, but we call it for completeness.
00345                 if (!(bretv=modelerp->UpdateModelAfterReceivingSymbol(symbolnumber,coderp)))
00346                         break;
00347                 }
00348 
00349         // return success
00350         return bretv;
00351 }
00352 //---------------------------------------------------------------------------
 
Generated on 20 May 2004 by doxygen 1.3.3