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

octanetester/octanetester.cpp

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 //---------------------------------------------------------------------------
00014 
00015 
00016 //---------------------------------------------------------------------------
00017 // application includes
00018 #include "octanetester.hpp"
00019 #include "../utilityclasses/stringparser/stringparser.hpp"
00020 #include "../utilityclasses/timer/timer.hpp"
00021 // system includes
00022 #include <iostream>
00023 #include <iomanip>
00024 #include <fstream>
00025 #include <cstdio>
00026 using namespace std;
00027 //---------------------------------------------------------------------------
00028 
00029 
00030 
00031 //---------------------------------------------------------------------------
00032 OctaneTester::OctaneTester()
00033 {
00034         // constructor
00035         currentcompressorp=NULL;
00036 }
00037 
00038 OctaneTester::~OctaneTester()
00039 {
00040         // destructor
00041 }
00042 //---------------------------------------------------------------------------
00043 
00044 
00045 
00046 //---------------------------------------------------------------------------
00047 void OctaneTester::ShowHelp()
00048 {
00049         cout << OCTANE_VERSIONSTRING << endl;
00050         cout << "Commands are case-sensitive (to use as commandline arguments separate with ';')"<< endl;
00051         cout << " Compression and Decompression"<<endl;
00052         cout << "  'compress $inputfile [$outputfile]' to compress a file+compressor." << endl;
00053         cout << "  'decompress $inputfile [$outputfile]' to decompress a file+compressor." << endl;
00054         cout << "  'compressr $inputfile [$outputfile]' to compress a file; save only raw data." << endl;
00055         cout << "  'decompressr $inputfile [$outputfile]' to decompress a file of raw data." << endl;
00056         cout << "  'test $text' to test compression and decompression a line of $text." << endl;
00057         cout << "  'testfile $inputfile' to test compression and decompression of a file." << endl;
00058         cout << " Compressor Creation, Configuration, and File Management"<<endl;
00059         cout << "  'compressors' to get a list of compressors and compressor classes." << endl;
00060         cout << "  'create $compressorclass' to instantiate a compressor class and select it."<<endl;
00061         cout << "  'setinfo $name [$GUID]' to set name and GUID for instantiated compressor."<<endl;
00062         cout << "  'select [$name|$num|G$guid]' to select an instantiated compressor." << endl;
00063         cout << "  'makestate $inputfile' to create state data using $inputfile." << endl;
00064         cout << "  'save $outputfile' to save current compressor (set GUID with setinfo)." << endl;
00065         cout << "  'load $inputfile' to load/instantiate a previously saved compressor." << endl;
00066         cout << "  'delete [$name|$num|G$guid]' to delete an instantiated compressor."<<endl;
00067         cout << " Miscellaneous Commands"<<endl;
00068         cout << "  'debug' to show debugging info for current compressor/dictionary." << endl;
00069         cout << "  'parameters' to see a list of available runtime parameters." << endl;
00070         cout << "  'set $parametername $value' to set a runtime parameter to some value." << endl;
00071         cout << "  'run $commandfile' to run octane commands from a file." << endl;
00072         cout << "  'help' to show these instructions." << endl;
00073         cout << "  'quit' to exit this program." << endl;
00074 
00075         // brief list of all compressors registered
00076         ListCompressors(true);
00077 
00078         // info about the current compressor being tested
00079         if (currentcompressorp==NULL)
00080                 {
00081                 //cout << "No instantiated compressor currently selected (do you need to run 'create' to instantiate one?)."<<endl;
00082                 }
00083         else
00084                 {
00085                 cout << "Current: " << currentcompressorp->GetInstantiatedName() << " ("<< currentcompressorp->GetDescription() <<")"<<endl;
00086                 // show any derived class intro information?
00087                 // currentcompressorp->ShowCompressorIntroInformation();
00088                 }
00089         }
00090 
00091 
00092 void OctaneTester::TestLoop()
00093 {
00094         // a built in test loop that just asks user for input and compresses and decompresses in debug mode
00095         // and lets user load and save files.
00096         std::string line;
00097 
00098         // show instructions
00099         ShowHelp();
00100         
00101         // loop processing user commands
00102         cout << '>';
00103         while (GrabLineFromConsole(line))
00104                 {
00105                 if (line == "quit")
00106                         break;
00107                 else if (line!="")
00108                         ParseCommand(line);
00109                 cout << '>';
00110                 }
00111 }
00112 //---------------------------------------------------------------------------
00113 
00114 
00115 
00116 //---------------------------------------------------------------------------
00117 bool OctaneTester::ParseCommand(const string &inputstr)
00118 {
00119         // process a single command, called from commandline or TestLoop above
00120         bool bretv=false;
00121         
00122         // return if no command provided
00123         if (inputstr.empty())
00124                 return false;
00125 
00126         // create parser for string
00127         stringparser parser(inputstr);
00128         // grab main command keyword
00129         string command(parser.get_token());
00130 
00131         // NOW PARSE COMMAND
00132 
00133         if (command == "version")
00134                 {
00135                 // version info
00136                 cout << OCTANE_VERSIONSTRING << endl;
00137                 return true;
00138                 }
00139         else if (command == "help")
00140                 {
00141                 // show help information
00142                 ShowHelp();
00143                 return true;
00144                 }
00145         else if (command == "debug")
00146                 {
00147                 // tell compressor to display any debug info it can
00148                 if (!CheckCompressorSelected(currentcompressorp))
00149                         return false;
00150                 currentcompressorp->ShowDebuggingInfo();
00151                 return true;
00152                 }
00153         else if (command == "compressors")
00154                 {
00155                 // list registered compressors
00156                 ListCompressors(false);
00157                 return true;
00158                 }
00159         else if (command == "parameters")
00160                 {
00161                 // list available parameters
00162                 if (!CheckCompressorSelected(currentcompressorp))
00163                         return false;
00164                 cout << currentcompressorp->GetParametersInformation();
00165                 return true;
00166                 }
00167         else if (command == "select")
00168                 {
00169                 // select a registered compressor
00170                 string param(parser.get_token());
00171                 if (param == "")
00172                         {
00173                         cout << "you must specify the instantiated compressor to select."<<endl;
00174                         return false;
00175                         }
00176                 if (SelectInstantiatedCompressor(param)==NULL)
00177                         {
00178                         cout << "error: compressor not found; type 'compressors' for a list of registered compressors."<<endl;
00179                         return false;
00180                         }
00181                 cout << "compressor "<< currentcompressorp->GetInstantiatedName() << " selected."<<endl;
00182                 return true;
00183                 }
00184         else if (command == "run")
00185                 {
00186                 // run octane commands from a file
00187                 string param(parser.get_token());
00188                 if (param == "")
00189                         {
00190                         cout << "you must specify the filename to run."<<endl;
00191                         return false;
00192                         }
00193                 return ExecuteCommandsFromFile(param,false);
00194                 }
00195         else if (command == "set")
00196                 {
00197                 // set a parameter
00198                 if (!CheckCompressorSelected(currentcompressorp))
00199                         return false;
00200                 string param1(parser.get_token());
00201                 if (param1 == "")
00202                         {
00203                         cout << "you must specify the parameter to set."<<endl;
00204                         return false;
00205                         }
00206                 string param2(parser.get_token());
00207                 if (param2 == "")
00208                         {
00209                         cout << "you must specify a value for the parameter."<<endl;
00210                         return false;
00211                         }
00212                 bretv = currentcompressorp->SetParameter(param1, param2);
00213                 if (bretv)
00214                         cout << "ok."<<endl;
00215                 else
00216                         cout << "error setting parameter or parameter not known."<<endl;
00217                 return bretv;
00218                 }
00219 
00220         else if (command == "load")
00221                 {
00222                 // load previously saved compressor
00223                 // note that this operation creates a new compressor, so we don't need to insist that an instantiated compressor
00224                 string param(parser.get_token());
00225                 if (param == "")
00226                         {
00227                         cout << "you must specify the filename to load the compressor from."<<endl;
00228                         return false;
00229                         }
00230                 // run the command
00231                 return RunCommand_LoadCompressor(param);
00232                 }
00233         else if (command == "save")
00234                 {
00235                 // load previously saved state
00236                 if (!CheckCompressorSelected(currentcompressorp))
00237                         return false;
00238                 string param(parser.get_token());
00239                 if (param == "")
00240                         {
00241                         cout << "you must specify the filename to save the compressor to."<<endl;
00242                         return false;
00243                         }
00244                 // run the command
00245                 return RunCommand_SaveCompressor(param);
00246                 }
00247         else if (command == "create")
00248                 {
00249                 // create a new compressor based on a compressor class
00250                 string param(parser.get_token());
00251                 if (param == "")
00252                         {
00253                         cout << "you must specify the base class of the compressor to build."<<endl;
00254                         return false;
00255                         }
00256                         
00257                 // optional name
00258                 string param2(parser.get_token());
00259 
00260                 // optional guid
00261                 string param3(parser.get_token());
00262                 short int guid=0;
00263                 if (param3!="")
00264                         guid=atoi(param3.c_str());
00265 
00266                 // run the command
00267                 bretv=RunCommand_CreateCompressor(param,param2,guid);
00268                 if (bretv)
00269                                 cout << "compressor "<< currentcompressorp->GetInstantiatedName() << " created and selected."<<endl;
00270                 return bretv;
00271                 }
00272 
00273         else if (command == "delete")
00274                 {
00275                 // load previously saved state
00276                 string param(parser.get_token());
00277                 if (param == "")
00278                         {
00279                         cout << "you must specify the instantiated compressor to delete."<<endl;
00280                         return false;
00281                         }
00282                 // run the command
00283                 bool bretv=RunCommand_DeleteCompressor(param);
00284                 if (bretv)
00285                         {
00286                         cout << "compressor deleted."<<endl;
00287                         return true;
00288                         }
00289                 }
00290 
00291         else if (command == "setinfo")
00292                 {
00293                 // set name and guid for a compressor
00294                 if (!CheckCompressorSelected(currentcompressorp))
00295                         return false;
00296                 string param(parser.get_token());
00297                 if (param == "")
00298                         {
00299                         cout << "you must specify a name for the compressor."<<endl;
00300                         return false;
00301                         }
00302                 string param2(parser.get_token());
00303                 // set the values
00304                 unsigned short int guidnum=0;
00305                 if (param2!="")
00306                         guidnum=atoi(param2.c_str());
00307                 currentcompressorp->SetInfo(param,guidnum);
00308                 cout << "compresser info changed."<<endl;
00309                 return true;
00310                 }
00311 
00312         else if (command == "makestate")
00313                 {
00314                 // make state information (i.e. build dictionary etc) using a file as training input
00315                 if (!CheckCompressorSelected(currentcompressorp))
00316                         return false;
00317                 string param1(parser.get_token());
00318                 if (param1 == "")
00319                         {
00320                         cout << "you must specify the filename to use for input."<<endl;
00321                         return false;
00322                         }
00323                 // run command
00324                 bool bretv=RunCommand_MakeState(param1);
00325                 cout << "  execution time:  "<< currentcompressorp->GetStatistics_LastOperation_State_ExecutionTime()<<" seconds."<<endl;
00326                 return bretv;
00327                 }
00328 
00329         else if (command == "compress")
00330                 {
00331                 // compress a file and write compressor info to front
00332                 if (!CheckCompressorReady(currentcompressorp))
00333                         return false;
00334                 string param1(parser.get_token());
00335                 if (param1 == "")
00336                         {
00337                         cout << "you must specify the filename to use."<<endl;
00338                         return false;
00339                         }
00340                 string param2(parser.get_token());
00341                 if (param2 == "")
00342                         {
00343                         // assume an output filename
00344                         param2 = MakeAssumedOutputFilename(param1, "decompressed", "compressed");
00345                         }
00346                 // run command (when savedecompresstateinfo==true it means write compressor state before raw data)
00347                 bool savedecompressstateinfo=true;
00348                 return RunCommand_Compress(param1,param2, savedecompressstateinfo);
00349                 }
00350         else if (command == "decompress")
00351                 {
00352                 // decompress a file and expect compressor state info at front
00353                 // we don't need an existing compressor for this decompress, since we expect full compressor state at head
00354                 //              if (!CheckCompressorReady(currentcompressorp))
00355                 //                      return false;
00356                 string param1(parser.get_token());
00357                 if (param1 == "")
00358                         {
00359                         cout << "you must specify the filename to use."<<endl;
00360                         return false;
00361                         }
00362                 string param2(parser.get_token());
00363                 if (param2 == "")
00364                         {
00365                         // assume an output filename
00366                         param2 = MakeAssumedOutputFilename(param1, "compressed", "decompressed");
00367                         }
00368                 // run command (when savedecompresstateinfo==false it means only write compressed data)
00369                 bool savedecompressstateinfo=true;
00370                 return RunCommand_Decompress(param1,param2,savedecompressstateinfo);
00371                 }
00372         else if (command == "compressr")
00373                 {
00374                 // compress a raw file without state info
00375                 if (!CheckCompressorReady(currentcompressorp))
00376                         return false;
00377                 string param1(parser.get_token());
00378                 if (param1 == "")
00379                         {
00380                         cout << "you must specify the filename to use."<<endl;
00381                         return false;
00382                         }
00383                 string param2(parser.get_token());
00384                 if (param2 == "")
00385                         {
00386                         // assume an output filename
00387                         param2 = MakeAssumedOutputFilename(param1, "decompressed", "compressed");
00388                         }
00389                 // run command (when savedecompresstateinfo==false it means only write compressed data)
00390                 bool savedecompressstateinfo=false;
00391                 return RunCommand_Compress(param1,param2, savedecompressstateinfo);
00392                 }
00393         else if (command == "decompressr")
00394                 {
00395                 // decompress a raw file, without compressor info
00396                 if (!CheckCompressorReady(currentcompressorp))
00397                         return false;
00398                 string param1(parser.get_token());
00399                 if (param1 == "")
00400                         {
00401                         cout << "you must specify the filename to use."<<endl;
00402                         return false;
00403                         }
00404                 string param2(parser.get_token());
00405                 if (param2 == "")
00406                         {
00407                         // assume an output filename
00408                         param2 = MakeAssumedOutputFilename(param1, "compressed", "decompressed");
00409                         }
00410                 // run command (when savedecompresstateinfo==false it means only write compressed data)
00411                 bool savedecompressstateinfo=false;
00412                 return RunCommand_Decompress(param1,param2,savedecompressstateinfo);
00413                 }
00414 
00415         else if (command == "testfile")
00416                 {
00417                 // compress and decompress a text string as a test
00418                 if (!CheckCompressorReady(currentcompressorp))
00419                         return false;
00420                 string param1(parser.get_token());
00421                 if (param1 == "")
00422                         {
00423                         cout << "you must specify the file to test compress."<<endl;
00424                         return false;
00425                         }
00426 
00427                 // run command
00428                 return RunCommand_TestFile(param1);
00429                 }
00430         else if (command == "test")
00431                 {
00432                 // compress and decompress a text string as a test
00433                 if (!CheckCompressorReady(currentcompressorp))
00434                         return false;
00435                 if (inputstr.length() <= 5)
00436                         {
00437                         cout << "error: you need to specify text to compress."<<endl;
00438                         return false;
00439                         }
00440                 // get text to compress
00441                 string inputstring(inputstr.substr(5));
00442                 // run command
00443                 return RunCommand_TestString(inputstring);
00444                 }
00445 
00446         // if we get here it means the command was not understood
00447         cout << "command not understood(" << inputstr << "); type 'help' for a list of known commands."<<endl;
00448         return false;
00449 }
00450 
00451 bool OctaneTester::ExecuteCommandsFromStream(std::ifstream &from, bool quiet)
00452         {
00453         // run a stream full of commands and time them
00454         // return true on success
00455         bool bretv=true;
00456 
00457         // record start time
00458         OctaneTimer octanetimer;
00459 
00460         // parse stream
00461         string line;
00462         int linenum=1;
00463         while (getline(from, line))
00464                 {
00465                 // skip comments and blank lines
00466                 string::size_type i = line.find_first_of("\015\012");
00467                 if (i != string::npos)
00468                         line.erase(i);
00469                 if (line.length() < 3)
00470                         continue;
00471                 if (line[0] == '/' && line[1] == '/')
00472                         continue;
00473                 // show debugging info
00474                 if (!quiet)
00475                         cout << "]" << line << ""<<endl;
00476                 // run it and stop on exit
00477                 if (!(bretv=ParseCommand(line)))
00478                         break;
00479                 ++linenum;
00480                 }
00481 
00482         if (!quiet)
00483                 {
00484                 if (bretv)
00485                         cout << "Script finished successfully after "<<octanetimer.stop()<<" seconds."<<endl;
00486                 else
00487                         cout << "Script aborted with error on line "<<linenum<< " after "<<octanetimer.stop()<<" seconds."<<endl;
00488                 }
00489 
00490         // return success
00491         return bretv;
00492         }
00493 
00494 
00495 bool OctaneTester::ExecuteCommandsFromFile(const std::string &filename, bool quiet)
00496         {
00497         // open a file input stream and run it
00498         // return true on success
00499         ifstream from(filename.c_str());
00500         if (!from)
00501                 {
00502                 cout << "error: unable to open file '" << filename << "'."<<endl;
00503                 return false;
00504                 }
00505         return ExecuteCommandsFromStream(from,quiet);
00506         }
00507 //---------------------------------------------------------------------------
00508 
00509 
00510 
00511 //---------------------------------------------------------------------------
00512 bool OctaneTester::GrabLineFromConsole(string &line)
00513 {
00514         // read a line of input from console and return true if a line was read or false if error ctrl-break type abort
00515         // we had to write this because of a known bug in vc6 getline() which requires double CRs on getline input.  good work bill gates.
00516         // return true on successful read of a line (can be blank)
00517 
00518         // clear line
00519         line="";
00520 
00521         // loop reading characters until CR
00522         unsigned char c;
00523         for (;;)
00524                 {
00525                 c = cin.get();
00526                 if (c=='\n')
00527                         break;
00528                 line+=c;
00529                 }
00530         return true;
00531 }
00532 
00533 
00534 void OctaneTester::ListCompressors(bool briefmode)
00535 {
00536         // list all registered compressors
00537         int index;
00538         OctaneCompressor *compressorp;
00539         string guidstr;
00540         char tempstr[16];
00541         int compressorcount;
00542         
00543         // Registered base compressor types
00544         cout << "Registered Compressor Types";
00545         if (briefmode)
00546                 cout <<": ";
00547         else
00548                 cout << "\n---------------------------"<<endl;
00549 
00550         compressorcount=global_compressormanagerp->GetBaseCompressorCount();
00551         if (compressorcount==0)
00552                 cout << "no base compressor types registered."; 
00553         for (index=0;index<compressorcount;++index)
00554                 {
00555                 compressorp=global_compressormanagerp->GetBaseCompressorp(index);
00556                 if (briefmode)
00557                         cout << compressorp->GetClassName() << " ";
00558                 else
00559                         cout << "  "<<setiosflags(ios::left) << setw(20) << compressorp->GetClassName() << " " << (compressorp->GetDescription()).c_str()<<endl;
00560                 }
00561         cout << endl;
00562 
00563         // Instantiated compressors
00564         cout << "Instantiated Compressors";
00565         if (briefmode)
00566                 cout <<":    ";
00567         else
00568                 cout << "\n------------------------"<<endl;
00569         compressorcount=global_compressormanagerp->GetInstantiatedCompressorCount();
00570         if (compressorcount==0)
00571                 cout << "(none)";
00572         int indexnum=0;
00573         string prefixstr;
00574         for (index=0;index<compressorcount;++index)
00575                 {
00576                 compressorp=global_compressormanagerp->GetInstantiatedCompressorp(index);
00577                 if (compressorp->GetCompressorStateFileGUID()!=0)
00578                         {
00579                         sprintf(tempstr,"GUID=%d",compressorp->GetCompressorStateFileGUID());
00580                         guidstr=string(tempstr);
00581                         }
00582                 else
00583                         guidstr="NOGUID";
00584                 // set prefix to indicate which one selected
00585                 if (currentcompressorp==compressorp)
00586                         prefixstr="*";
00587                 else
00588                         prefixstr=" ";
00589                 //
00590                 if (briefmode)
00591                         cout << "["<<indexnum<< prefixstr << compressorp->GetInstantiatedName() << " " << guidstr << "] ";
00592                 else
00593                         cout << " "<< prefixstr << setiosflags(ios::left) << setw(4) << indexnum << " " << setiosflags(ios::left) << setw(20) << compressorp->GetInstantiatedName() << " " << (compressorp->GetDescription()).c_str()<< " ("<< guidstr<<")"<<endl;
00594                 ++indexnum;
00595                 }
00596         cout << endl;
00597 }
00598 
00599 OctaneCompressor* OctaneTester::SelectInstantiatedCompressor(const string &compressorname)
00600 {
00601         // lookup compressor
00602         OctaneCompressor* compressorp=global_compressormanagerp->FindInstantiatedCompressorpFromStringId(compressorname);
00603         // set current compressor
00604         if (compressorp!=NULL)
00605                 currentcompressorp=compressorp;
00606         return compressorp;
00607 }
00608 
00609 bool OctaneTester::CheckCompressorSelected(OctaneCompressor *compressorp)
00610 {
00611         // check if the compressor is nonnull and is ready
00612         // show warning and return false if not.
00613         if (compressorp==NULL)
00614                 {
00615                 cout << "No instantiated compressor currently selected (run 'create' or 'load')."<<endl;
00616                 return false;
00617                 }
00618         // one is selected
00619         return true;
00620 }
00621 
00622 bool OctaneTester::CheckCompressorReady(OctaneCompressor *compressorp)
00623         {
00624         // check if the compressor is nonnull and is ready
00625         // show warning and return false if not.
00626         if (!CheckCompressorSelected(compressorp))
00627                 return false;
00628         if (!compressorp->IsReadyToCompress())
00629                 {
00630                 cout << "compressor "<< currentcompressorp->GetInstantiatedName() << " is not ready for compression; do you need to make or load state data first?"<<endl;
00631                 return false;
00632                 }
00633         // it is ready
00634         return true;
00635         }
00636 
00637 string OctaneTester::MakeAssumedOutputFilename(const string &origname, const string &origext, const string &newext)
00638 {
00639         // helper function to smartly add an extension to a file name, based on current compressor
00640         //  and removing old extension if appropriate.
00641 
00642         if (currentcompressorp==NULL)
00643                 {
00644                 string origfullext(string(".") + origext);
00645                 string::size_type pos = origname.rfind(origfullext);
00646                 if (pos == string::npos)
00647                         return origname + "." + newext;
00648                 return string(origname, 0, pos) + newext;
00649                 }
00650 
00651         string newfullext(string(".") + currentcompressorp->GetInstantiatedName() + "." + newext);
00652 
00653         if (origext == "")
00654                 return origname + newfullext;
00655 
00656         string origfullext(string(".") + currentcompressorp->GetInstantiatedName() + "." + origext);
00657 
00658         string::size_type pos = origname.rfind(origfullext);
00659 
00660         if (pos == string::npos)
00661                 return origname + "." + newext;
00662 
00663         return string(origname, 0, pos) + newext;
00664 }
00665 //---------------------------------------------------------------------------
00666 
00667 
00668 
00669 //---------------------------------------------------------------------------
00670 bool OctaneTester::RunCommand_TestString(std::string inputstring)
00671         {
00672         bool bretv;
00673         // create bitreader and bitwriter, they will be deleted on exit
00674         string compressedstring;
00675         string_bitreader from(inputstring);
00676         string_bitwriter to(compressedstring);
00677 
00678         // do compression of text (third argument==false means don't write header info)
00679         bretv = currentcompressorp->Compress(from, to, false, false);
00680         if (!bretv)
00681                 {
00682                 cout << "Error compressing."<<endl;
00683                 return false;
00684                 }
00685 
00686         // align output bitwriter (this must be performed when we finish)
00687         to.align_byte();
00688 
00689         // show some info about compression
00690         cout << "Testing " << currentcompressorp->GetInstantiatedName() << ".."<<endl;
00691         cout << "  input length: " << setw(3)<< (int)(inputstring.length()) << "\n";
00692         cout << " output length: " << setw(3)<< (int)(compressedstring.length()) << endl;
00693 
00694         // show result in nice format
00695         string nicestring(compressedstring);
00696         NiceifyHighAsciiString(nicestring);
00697         cout << "    compressed: " << nicestring << endl;
00698 
00699         // decompress it back to original to check it
00700         // create bitreader and bitwriter, they will be deleted on exit
00701         string resultstring;
00702         string_bitreader from2(compressedstring);
00703         string_bitwriter to2(resultstring);
00704         // do decompression (third argument==false means don't expect header info)
00705         bretv = currentcompressorp->Decompress(from2, to2, false);
00706         if (!bretv)
00707                 {
00708                 cout << "Error decompressing."<<endl;
00709                 return false;
00710                 }
00711 
00712         // show result
00713         cout << "      original: "<< inputstring << "\n";
00714         cout << "  decompressed: "<< resultstring << endl;
00715         if (inputstring != resultstring)
00716                 {
00717                 cout << "ERROR: decompression does not match original text."<<endl;
00718                 return false;
00719                 }
00720 
00721         // we are done with success
00722         return true;
00723         }
00724 
00725 
00726 bool OctaneTester::RunCommand_TestFile(std::string filename)
00727         {
00728         bool bretv,bretv2;
00729         std::string tempoutfilename_compressed="testfiletemp_compressed.out";
00730         std::string tempoutfilename_decompressed="testfiletemp_decompressed.out";
00731         
00732         // compress file with no state info
00733         cout << "Compressing file without state: ";
00734         bretv=RunCommand_Compress(filename,tempoutfilename_compressed,false);
00735         if (bretv)
00736                 {
00737                 cout << "Decompressing compressed file: ";
00738                 bretv=RunCommand_Decompress(tempoutfilename_compressed,tempoutfilename_decompressed,false);
00739                 if (bretv)
00740                         {
00741                         // now see if they are identical
00742                         cout << "--> Comparing decompressed file with original: ";
00743                         if (CheckFilesAreIdentical(tempoutfilename_decompressed,filename))
00744                                 cout << "FILES MATCH."<<endl;
00745                         else
00746                                 cout << "FILES DO *NOT* MATCH."<<endl;
00747                         }
00748                 }
00749         cout << endl;
00750                 
00751         // again with state
00752         cout << "Compressing file with state: ";
00753         bretv2=RunCommand_Compress(filename,tempoutfilename_compressed,true);
00754         if (bretv2)
00755                 {
00756                 cout << "Decompressing compressed file: ";
00757                 bretv2=RunCommand_Decompress(tempoutfilename_compressed,tempoutfilename_decompressed,true);
00758                 if (bretv2)
00759                         {
00760                         // now see if they are identical
00761                         cout << "--> Comparing decompressed file with original: ";
00762                         if (CheckFilesAreIdentical(tempoutfilename_decompressed,filename))
00763                                 cout << "FILES MATCH."<<endl;
00764                         else
00765                                 cout << "FILES DO *NOT* MATCH."<<endl;
00766                         }
00767                 }
00768         cout << endl;
00769 
00770         // now delete temporary files
00771         DeleteAFile(tempoutfilename_compressed);
00772         DeleteAFile(tempoutfilename_decompressed);
00773         
00774         // return success
00775         return (bretv&&bretv2);
00776         }
00777 //---------------------------------------------------------------------------
00778 
00779 
00780 
00781 //---------------------------------------------------------------------------
00782 bool OctaneTester::RunCommand_CreateCompressor(std::string compressorclassname,std::string compressorname, unsigned short guidnum)
00783 {
00784         // create a new compressor based on a base class
00785 
00786         // select base compressor class type
00787         OctaneCompressor *compressorp = global_compressormanagerp->FindBaseCompressorClass(compressorclassname);
00788         if (compressorp==NULL)
00789                 {
00790                 // couldn't find base class
00791                 cout << "ERROR: could not find compressor base class '"<<compressorclassname<<"'."<<endl;
00792                 return false;
00793                 }
00794 
00795         // ask base class to make us a derived class
00796         compressorp=compressorp->MakeCompressorInstantiation();
00797         if (compressorp==NULL)
00798                 {
00799                 // couldn't find base class
00800                 cout << "ERROR: failed to instantiate a derived compressor from base class '"<<compressorclassname<<"'."<<endl;
00801                 return false;
00802                 }
00803 
00804         // set details for it
00805         compressorp->SetInfo(compressorname,guidnum);
00806         
00807         // now add it
00808         bool bretv=global_compressormanagerp->AddCompressor(compressorp);
00809         if (!bretv)
00810                 {
00811                 // failed to add it
00812                 delete compressorp;
00813                 return false;
00814                 }
00815         else
00816                 {
00817                 // set this new compressor to be our current compressor?
00818                 if (currentcompressorp==NULL || true)
00819                         currentcompressorp=compressorp;
00820                 }
00821         
00822         return true;
00823 }
00824 
00825         
00826 bool OctaneTester::RunCommand_LoadCompressor(std::string filename)
00827         {
00828         // create bitreader, they will be deleted on exit
00829         file_bitreader from(filename.c_str());
00830         if (from.error())
00831                 {
00832                 cout << "Error opening file " << filename << " for input.  Loadstate failed."<<endl;
00833                 return false;
00834                 }
00835         // load the state
00836         OctaneCompressor * compressorp= global_compressormanagerp->CreateCompressorFromSavedStream(from);
00837         if (compressorp==NULL)
00838                 {
00839                 cout <<"Failed to load compressor."<<endl;
00840                 return false;
00841                 }
00842                 
00843         // add compressor
00844         bool bretv=global_compressormanagerp->AddCompressor(compressorp);
00845         if (bretv==false)
00846                 {
00847                 cout <<"Failed to add compressor to compressor manager."<<endl;
00848                 delete compressorp;
00849                 return false;
00850                 }
00851         else
00852                 {
00853                 // set this new compressor to be our current compressor?
00854                 if (currentcompressorp==NULL || true)
00855                         currentcompressorp=compressorp;
00856                 }
00857 
00858         // show results
00859         cout << "Loaded compressor from file '" << filename << "'.\n";
00860         cout << "  state file size: "<< currentcompressorp->GetStatistics_LastOperation_State_BytesRead()<<" bytes.\n";
00861         cout << "  execution time:  "<< currentcompressorp->GetStatistics_LastOperation_State_ExecutionTime()<<" seconds."<<endl;
00862         // show new compressor info
00864 
00865         // return success
00866         return true;
00867         }
00868 
00869 
00870 bool OctaneTester::RunCommand_SaveCompressor(std::string filename)
00871         {
00872         // create bitreader, they will be deleted on exit
00873         file_bitwriter to(filename.c_str());
00874         if (to.error())
00875                 {
00876                 cout << "Error opening file " << filename << " for input.  SaveCompressor failed."<<endl;
00877                 return false;
00878                 }
00879         // save the state (second parameter==false means save complete state, not just state required for decompression)
00880         bool bretv = currentcompressorp->Save(to,false);
00881         if (!bretv)
00882                 {
00883                 cout <<"Failed to save state data."<<endl;
00884                 return false;
00885                 }
00886         // show result
00887         cout << "Saved compressor file '" << filename << "'.\n";
00888         cout << "  state file size: "<< currentcompressorp->GetStatistics_LastOperation_State_BytesWritten()<<" bytes.\n";
00889 
00890         // return success
00891         return true;
00892         }
00893 
00894 
00895 bool OctaneTester::RunCommand_DeleteCompressor(std::string compressoridstring)
00896         {
00897         // delete a compressor
00898         
00899         // look up the compressor
00900         OctaneCompressor *compressorp = global_compressormanagerp->FindInstantiatedCompressorpFromStringId(compressoridstring);
00901         if (compressorp==NULL)
00902                 {
00903                 cout <<"Couldn't locate compressor '"<<compressoridstring<<"'."<<endl;
00904                 return false;
00905                 }
00906 
00907         // delete it
00908         global_compressormanagerp->DeleteCompressor(compressorp);
00909 
00910         // if this was our current one, then we need to change it
00911         if (currentcompressorp==compressorp)
00912                 {
00913                 if (global_compressormanagerp->GetInstantiatedCompressorCount()>0)
00914                         currentcompressorp=global_compressormanagerp->GetInstantiatedCompressorp(0);
00915                 else
00916                         currentcompressorp=NULL;
00917                 }
00918 
00919         // return success
00920         return true;
00921         }
00922 
00923 
00924 bool OctaneTester::RunCommand_MakeState(std::string infilename)
00925         {
00926         // create bitreader and bitwriter, they will be deleted on exit
00927         file_bitreader from(infilename.c_str());
00928         if (from.error())
00929                 {
00930                 cout << "Error opening file "<<infilename<< " for input.  Makestate failed."<<endl;
00931                 return false;
00932                 }
00933 
00934         // make state data
00935         cout << "Computing state data using "<<currentcompressorp->GetInstantiatedName() << ":"<<endl;
00936         bool bretv = currentcompressorp->CreateSymbolsAndModelsUsingStream(from);
00937         if (!bretv)
00938                 {
00939                 cout << "Failed to generate state data."<<endl;
00940                 return false;
00941                 }
00942         return true;
00943         }
00944 
00945 
00946 bool OctaneTester::RunCommand_Compress(std::string infilename,std::string outfilename, bool savedecompressstateinfo)
00947         {
00948         // create bitreader and bitwriter, they will be deleted on exit
00949         file_bitreader from(infilename.c_str());
00950         if (from.error())
00951                 {
00952                 cout << "Error opening file " << infilename << " for input.  Compression failed."<<endl;
00953                 return false;
00954                 }
00955         file_bitwriter to(outfilename.c_str());
00956         if (to.error())
00957                 {
00958                 cout << "Error opening file " << outfilename << " for output.  Compression failed."<<endl;
00959                 return false;
00960                 }
00961 
00962         // do the compression
00963         cout << "Compressing with " << currentcompressorp->GetInstantiatedName() << ":"<<endl;
00964         bool bretv = currentcompressorp->Compress(from, to, savedecompressstateinfo, savedecompressstateinfo);
00965         if (!bretv)
00966                 {
00967                 cout << "Compression failed."<<endl;
00968                 return false;
00969                 }
00970 
00971         // show output
00972         cout << "       original size: " << currentcompressorp->GetStatistics_LastOperation_Compression_BytesRead() << " bytes (" << infilename << ")\n";
00973         cout << "     compressed size: " << currentcompressorp->GetStatistics_LastOperation_Compression_BytesWritten() << " bytes (" << outfilename << ")\n";
00974         if (savedecompressstateinfo)
00975                 cout << " est. cost of header: " << currentcompressorp->GetDiskspaceUsed(true)<< " bytes.\n";
00976         float executiontime=currentcompressorp->GetStatistics_LastOperation_Compression_ExecutionTime();
00977         float bytespersec=(currentcompressorp->GetStatistics_LastOperation_Compression_BytesRead()/executiontime)/1024.0;
00978         cout << "      execution time: " <<  executiontime << " seconds ("<<bytespersec<<" kb/s).\n";
00979         cout << "   compression ratio: " << currentcompressorp->GetStatistics_LastOperation_Compression_Ratio()*100.0 << "% (" << currentcompressorp->GetStatistics_LastOperation_Compression_Bitrate() << " bits per byte)."<<endl;
00980 
00981         // return success
00982         return true;
00983         }
00984 
00985 
00986 bool OctaneTester::RunCommand_Decompress(std::string infilename,std::string outfilename, bool savedecompressstateinfo)
00987         {
00988         // create bitreader and bitwriter, they will be deleted on exit
00989         OctaneCompressor *compressorp;
00990         int headersize=0;
00991 
00992         file_bitreader from(infilename.c_str());
00993         if (from.error())
00994                 {
00995                 cout << "Error opening file " << infilename << " for input.  Decompression failed."<<endl;
00996                 return false;
00997                 }
00998         file_bitwriter to(outfilename.c_str());
00999         if (to.error())
01000                 {
01001                 cout << "Error opening file " << outfilename << " for output.  Decompression failed."<<endl;
01002                 return false;
01003                 }
01004 
01005         if (savedecompressstateinfo)
01006                 {
01007                 // first read guid info - and if found try to create a compressor from known compressors
01008                 int retvguid=OctaneCompressor::LoadGUID(from);
01009                 if (retvguid==-1)
01010                         {
01011                         // compressor details are in from stream
01012                         compressorp=global_compressormanagerp->CreateCompressorFromSavedStream(from);
01013                         if (compressorp==NULL)
01014                                 {
01015                                 cout << "Error creating compressor from the input stream."<<endl;
01016                                 return false;
01017                                 }
01018                         headersize=from.tell_byte();
01019                         // cout << "Recreated temporary compressor from input stream."<<endl;
01020                         }
01021                 else
01022                         {
01023                         // only the guid is in the from stream, now we have to look it up
01024                         compressorp=global_compressormanagerp->FindInstantiatedCompressorpFromGuid(retvguid);
01025                         if (compressorp==NULL)
01026                                 {
01027                                 cout << "Error, could not find an instantiated compressor which matches input stream expectation(GUID="<<retvguid<<")."<<endl;
01028                                 return false;
01029                                 }
01030                         cout << "Using instantiated compressor with guid "<<retvguid<<"."<<endl;
01031                         }
01032                 }
01033         else
01034                 {
01035                 // use current compressor
01036                 compressorp=currentcompressorp;
01037                 }
01038 
01039         // do the decompression
01040         cout << "Decompressing with " << compressorp->GetInstantiatedName() << ":"<<endl;
01041         // we pass the last argument false because we have already loaded any compressor state data
01042         bool bretv = compressorp->Decompress(from, to, false);
01043         if (!bretv)
01044                 cout << "Decompression failed."<<endl;
01045         else
01046                 {
01047                 // kludge to fixup lastoperation size to account for header size
01048                 compressorp->Add_LastOperation_Decompression_BytesRead(headersize);
01049                 // show result
01050                 cout <<"      original size: "  << compressorp->GetStatistics_LastOperation_Decompression_BytesRead() << " (" << infilename << ")\n";
01051                 cout << "  decompressed size: " << compressorp->GetStatistics_LastOperation_Decompression_BytesWritten() << " (" << outfilename << ")\n";
01053                 float executiontime=compressorp->GetStatistics_LastOperation_Decompression_ExecutionTime();
01054                 float bytespersec=(currentcompressorp->GetStatistics_LastOperation_Decompression_BytesWritten()/executiontime)/1024.0;
01055                 cout << "     execution time: " << executiontime << " seconds ("<<bytespersec<<" kb/s).\n";
01056                 cout << "  compression ratio: " << compressorp->GetStatistics_LastOperation_Decompression_Ratio()*100.0 << "% (" << compressorp->GetStatistics_LastOperation_Decompression_Bitrate() << " bits per byte)."<<endl;
01057                 }
01058 
01059         if (savedecompressstateinfo)
01060                 {
01061                 // kill the temporary compressor
01062                 delete compressorp;
01063                 }
01064 
01065         // return success
01066         return bretv;
01067         }
01068 //---------------------------------------------------------------------------
01069 
01070 
01071 
01072 //---------------------------------------------------------------------------
01073 bool OctaneTester::DeleteAFile(std::string filename)
01074 {
01075         // helper function, delete a file if it exists, or do nothing if not
01076 
01077         remove(filename.c_str());
01078 
01079         // return true on deletion of file or no file
01080         return true;
01081 }
01082 
01083 bool OctaneTester::CheckFilesAreIdentical(std::string filename1,std::string filename2)
01084 {
01085         // test files for equality
01086 
01087         // inefficient way but works
01088 
01089         file_bitreader from1(filename1.c_str());
01090         file_bitreader from2(filename2.c_str());
01091         if (from1.error() || from2.error())
01092                 {
01093                 // error
01094                 return false;
01095                 }
01096         
01097         if (from1.bytes_left()!=from2.bytes_left())
01098                 {
01099                 // dont match
01100                 return false;
01101                 }
01102 
01103         int len=from1.bytes_left();
01104         unsigned char c1,c2;
01105         while (len>0)
01106                 {
01107                 c1=from1.get_byte();
01108                 c2=from2.get_byte();
01109                 if (c1!=c2)
01110                         return false;
01111                 --len;
01112                 }
01113 
01114         // return true on success
01115         return true;
01116 }
01117 //---------------------------------------------------------------------------
 
Generated on 20 May 2004 by doxygen 1.3.3