home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 September / Chip_2002-09_cd1.bin / zkuste / vbasic / Data / Utils / XZipComp.exe / XceedEncoding.Cab / F112916_Encode.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-05-11  |  14.4 KB  |  423 lines

  1. /* Xceed Binary Encoding Library - Encode Sample Application
  2.  * Copyright (c) 2001 Xceed Software Inc.
  3.  *
  4.  * [Encode.cpp]
  5.  *
  6.  * This console application shows how to encode a file, using 
  7.  * different encoding methods. It specifically demonstrates:
  8.  *  - The ReadFile and ProcessFile methods.
  9.  *  - The EndOfLineType, MaxLineLength, EncodingFormat, 
  10.  *    DataFormating, HeaderDataForkLen and HeaderResourceForkLen properties 
  11.  *    from the various Encoding format interfaces.
  12.  *
  13.  * This file is part of the Xceed Binary Encoding Library sample 
  14.  * applications. The source code in this file is only intended as 
  15.  * a supplement to Xceed Binary Encoding Library's documentation, 
  16.  * and is provided "as is", without warranty of any kind, either 
  17.  * expressed or implied. 
  18.  */
  19.  
  20. #include "stdafx.h"
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <limits.h>
  24. #include "Encode.h"
  25.  
  26. //
  27. // Mapping between command-line and enumeration values
  28. //
  29.  
  30. static SEncodingMethod g_pxEncodingMethods[] = 
  31. {
  32.   { "=UU",      emUUEncode }, //Default
  33.   { "=XX",      emXXEncode },
  34.   { "=Base64",  emBase64 },
  35.   { "=Hex",     emHexadecimal },
  36.   { "=QP",      emQuotedPrintable },
  37.   { "=BHex",    emBinHex },
  38. };
  39.  
  40.  
  41. //--------------------------------------------------------------------------
  42. // Entry point of the application
  43. //--------------------------------------------------------------------------
  44. int main(int argc, char* argv[])
  45. {
  46.   // Initializes the COM library on the current thread following the STA model
  47.   CoInitialize( NULL );
  48.  
  49.   try
  50.   {
  51.     // Create an instance of the XceedBinaryEncoding coclass, and
  52.     // use the "I" interface which manipulates byte arrays instead of
  53.     // Variants as the "D" interface does.
  54.     IXceedBinaryEncodingPtr piEncoding;
  55.     piEncoding.CreateInstance( CLSID_XceedBinaryEncoding );
  56.  
  57.     // Two BSTR variables that will contain the Input and Output file names.
  58.     _bstr_t bstrInputFileName;
  59.     _bstr_t bstrOutputFileName;
  60.  
  61.     // Extract the command line parameters and initialize the Encoding 
  62.     // instance according to the user specification. After this call
  63.     // the Encoding instance piEncoding is ready to encode.
  64.     if( !ExtractParameters( argc, argv, 
  65.                             piEncoding,
  66.                             bstrInputFileName, 
  67.                             bstrOutputFileName ) )
  68.     {
  69.       ShowHelp();
  70.       return 1;
  71.     }
  72.  
  73.     if( bstrOutputFileName.length() == 0 )
  74.     {
  75.       // An output file name was not provided by the user.
  76.       // Output the result to the console.
  77.  
  78.       BYTE* pcEncoded     = NULL;
  79.       DWORD dwEncodedSize = 0;
  80.       DWORD dwBytesRead   = 0;
  81.  
  82.       // Encode by reading a file and sending the output to a buffer.
  83.       // We specify :
  84.       //  - The Source filename, without an offset or size, since we want
  85.       //    to encode all the source file.
  86.       //  - The processing we want to perform, in this case bfpEncode.
  87.       //  - The bEndOfData parameter set to TRUE, since we do all the
  88.       //    processing in a single block.
  89.       //  - The address of a DWORD that will receive the number of bytes 
  90.       //    actually read from the file.
  91.       //  - The address of a BYTE* and a DWORD that will receive the 
  92.       //    encoded data and its size.
  93.       piEncoding->ReadFile( bstrInputFileName, 0, 0, 
  94.                             bfpEncode, TRUE, 
  95.                             &dwBytesRead, &pcEncoded, &dwEncodedSize );
  96.  
  97.       if( pcEncoded )
  98.       {
  99.         // We simply output the encoded data to the console.
  100.         fwrite( pcEncoded, sizeof( BYTE ), dwEncodedSize, stdout );
  101.  
  102.         // Always free the resulting data using the CoTaskMemFree COM API 
  103.         // function.
  104.         CoTaskMemFree( pcEncoded );
  105.       }
  106.     }
  107.     else
  108.     {
  109.       // An output file name was provided by the user.
  110.       // Output the result to the specified file
  111.  
  112.       DWORD dwBytesRead     = 0;
  113.       DWORD dwBytesWritten  = 0;
  114.  
  115.       // Encode by reading a file and sending the output to another file.
  116.       // We specify :
  117.       //  - The source filename, without any offset or size, since we want
  118.       //    to encode all the source file.
  119.       //  - The processing we want to perform, in this case bfpEncode.
  120.       //  - The bEndOfData parameter set to TRUE, since we do all the
  121.       //    processing in a single block.
  122.       //  - The destination filename, with the bAppend parameter set to FALSE
  123.       //    since we want to overwrite any existing file.
  124.       //  - The address of two DWORD that will receive the number of bytes
  125.       //    actually read from the source, and written to the destination.
  126.       piEncoding->ProcessFile( bstrInputFileName, 0, 0, 
  127.                                bfpEncode, TRUE, 
  128.                                bstrOutputFileName, FALSE, 
  129.                                &dwBytesRead, &dwBytesWritten );
  130.  
  131.       printf( "Successfully encoded file %s to file %s\n", 
  132.               ( const char* )bstrInputFileName, ( const char* )bstrOutputFileName );
  133.     }
  134.   }
  135.   catch( const _com_error& err )
  136.   {
  137.     // When using the "#import" directive, the compiler generates wrapper classes
  138.     // around all interface types. These wrapper classes throw exceptions when
  139.     // a method call returns an HRESULT which is a failure code.
  140.     printf( "Error %08x: %s\n", err.Error(), ( const char* )err.Description() );
  141.   }
  142.   catch( ... )
  143.   {
  144.     // Catch any other exceptions
  145.     printf( "An unknown error occured.\n" );
  146.   }
  147.  
  148.   // Close the COM library for the current thread
  149.   CoUninitialize();
  150.  
  151.     return 0;
  152. }
  153.  
  154. //--------------------------------------------------------------------------
  155. // Display usage information
  156. //--------------------------------------------------------------------------
  157. void ShowHelp()
  158. {
  159.   //      "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
  160.   printf( "Usage: Encode [options] input_file [output_file]\n\n"
  161.           "  input_file: the file to be encoded\n"
  162.           "  output_file: the destination file\n\n"
  163.           "  options: /m=[UU | XX | Base64 | Hex : Encoding method\n"
  164.           "               QP | BHex]               if omited, default to UU\n"
  165.           "           /t=[CrLf | Lf] : End of line type\n"
  166.           "                            if omited, default to CrLf\n"
  167.           "           /l=######### : Maximum line length between ends of line delimiter\n"
  168.           "                          Can be from 1 to 999999999\n"
  169.           "                          if omited, default to 78\n"
  170.           "           /h or /? : Show this help\n" );
  171. }
  172.  
  173. //--------------------------------------------------------------------------
  174. // Extract commands from the parameters
  175. //
  176. // In this function, we call the piEncode interface and let exceptions
  177. // be caught by the caller.
  178. // This function returns false if an error occured parsing the command
  179. // line parameters or if the user requested help.
  180. //--------------------------------------------------------------------------
  181. bool ExtractParameters( int argc, char* argv[],
  182.                         IXceedBinaryEncodingPtr piEncode, 
  183.                         _bstr_t& bstrInputFileName,
  184.                         _bstr_t& bstrOutputFileName )
  185. {
  186.   // These variables used to initialize the Encoding format property
  187.   // are set, here, to their default values.
  188.   SEncodingMethod*  pxMethod = g_pxEncodingMethods;
  189.   EXBEndOfLineType  eEOLType = bltCrLf;
  190.   DWORD             dwMaxLineLength = 78;
  191.   
  192.   bool bFound;
  193.  
  194.   // We parse each command line parameter
  195.   int i = 0;
  196.   while( ++i < argc )
  197.   {
  198.     if( argv[ i ][ 0 ] == '/' )
  199.     {
  200.       // The parameter starts with a /
  201.       // Meaning it's an option parameter
  202.       switch( argv[ i ][ 1 ] )
  203.       {
  204.         case 'm':
  205.         case 'M':
  206.           {
  207.             // The user wants to set the encoding method
  208.             bFound = false;
  209.  
  210.             // We go through all the encoding methods in the 
  211.             // correspondence table, stopping when we find a 
  212.             // match.
  213.             for( pxMethod = g_pxEncodingMethods;
  214.                  pxMethod->pszCommandLine != NULL;
  215.                  pxMethod++ )
  216.             {
  217.               if( lstrcmpi( argv[ i ] + 2, pxMethod->pszCommandLine ) == 0 )
  218.               {
  219.                 bFound = true;
  220.                 break;
  221.               }
  222.             }
  223.  
  224.             if( !bFound )
  225.             {
  226.               printf( "Invalid encoding method '%s'\n\n", argv[ i ] );
  227.               return false;
  228.             }
  229.           }
  230.           break;
  231.  
  232.         case 't':
  233.         case 'T':
  234.           // The user wants to set the End of line type
  235.           if( lstrcmpi( argv[ i ] + 2, "=CrLf" ) == 0 )
  236.           {
  237.             eEOLType = bltCrLf;
  238.           }
  239.           else if( lstrcmpi( argv[ i ] + 2, "=Lf" ) == 0 )
  240.           {
  241.             eEOLType = bltLf;
  242.           }
  243.           else
  244.           {
  245.             printf( "Invalid end-of-line type '%s'\n\n", argv[ i ] );
  246.             return false;
  247.           }
  248.  
  249.           break;
  250.  
  251.         case 'l':
  252.         case 'L':
  253.           // The user wants to set the MaxLineLength
  254.           bFound = false;
  255.  
  256.           if( argv[ i ][ 2 ] == '=' )
  257.           {
  258.             char* pcStop;
  259.             DWORD dwLength = strtoul( argv[ i ] + 3, &pcStop, 10 );
  260.  
  261.             if( dwLength != ULONG_MAX )
  262.             {
  263.               dwMaxLineLength = dwLength;
  264.               bFound = true;
  265.             }
  266.           }
  267.  
  268.           if( !bFound )
  269.           {
  270.             printf( "Invalid maximum line length '%s'\n\n", argv[ i ] );
  271.             return false;
  272.           }
  273.  
  274.           break;
  275.  
  276.         default:
  277.           printf( "Unknown command '%s'\n\n", argv[ i ] );
  278.           // Continue
  279.         case 'h':
  280.         case 'H':
  281.         case '?':
  282.           return false;
  283.       }
  284.     }
  285.   }
  286.  
  287.   // Check if the user provided an input file name
  288.   if( argc < 2 || argv[ argc - 1 ][ 0 ] == '/' )
  289.   {
  290.     printf( "You did not specify an input filename\n\n" );
  291.     return false;
  292.   }
  293.   else if( argc < 3 || argv[ argc - 2 ][ 0 ] == '/' )
  294.   {
  295.     // Only an input file was specified
  296.     bstrInputFileName = argv[ argc - 1 ];
  297.   }
  298.   else
  299.   {
  300.     // Both input and output file were specified
  301.     bstrInputFileName   = argv[ argc - 2 ];
  302.     bstrOutputFileName  = argv[ argc - 1 ];
  303.   }
  304.  
  305.   // According the Encoding method chosen by the user, we set the various 
  306.   // properties of an encoding format and prepare the 
  307.   // Encoding interface (piEncode).
  308.  
  309.   // The properties common to all encoding format are:
  310.   // EndOfLineType and MaxLineLength
  311.  
  312.   // For each encoding method, we begin by creating a temporary instance 
  313.   // of the appropriate Encoding format. The properties of this instance
  314.   // are then set and the instance is assign to the EncodingFormat property
  315.   // of the XceedBinaryEncoding instance. This adds a reference to the 
  316.   // Encoding format instance so that the instance will not be freed
  317.   // when it will fall out of scope.
  318.  
  319.   switch( pxMethod->eMethod )
  320.   {
  321.     case emUUEncode :
  322.     {
  323.       IXceedUUEncodingFormatPtr piUUFormat;
  324.       
  325.       piUUFormat.CreateInstance( CLSID_XceedUUEncodingFormat );
  326.       // Set the type of End of line chosen by the user (or the default value).
  327.       piUUFormat->EndOfLineType = eEOLType;
  328.       // Set the maximum line length specified by the user (or the default value).
  329.       piUUFormat->MaxLineLength = dwMaxLineLength;
  330.       // We want the output file to have header and footer
  331.       piUUFormat->IncludeHeaderFooter = TRUE;
  332.       piEncode->EncodingFormat = IXceedEncodeDataPtr( piUUFormat );
  333.     }
  334.     break;
  335.  
  336.     case emXXEncode :
  337.     {
  338.       IXceedXXEncodingFormatPtr piXXFormat;
  339.       
  340.       piXXFormat.CreateInstance( CLSID_XceedXXEncodingFormat );
  341.       piXXFormat->EndOfLineType = eEOLType;
  342.       piXXFormat->MaxLineLength = dwMaxLineLength;
  343.       // We want the output file to have header and footer
  344.       piXXFormat->IncludeHeaderFooter = TRUE;
  345.       piEncode->EncodingFormat = IXceedEncodeDataPtr( piXXFormat );
  346.     }
  347.     break;
  348.  
  349.     case emBase64 :
  350.     {
  351.       IXceedBase64EncodingFormatPtr piBase64Format;
  352.       
  353.       piBase64Format.CreateInstance( CLSID_XceedBase64EncodingFormat );
  354.       piBase64Format->EndOfLineType = eEOLType;
  355.       piBase64Format->MaxLineLength = dwMaxLineLength;
  356.       piEncode->EncodingFormat = IXceedEncodeDataPtr( piBase64Format );
  357.     }
  358.     break;
  359.  
  360.     case emHexadecimal :
  361.     {
  362.       IXceedHexaEncodingFormatPtr piHexaFormat;
  363.       
  364.       piHexaFormat.CreateInstance( CLSID_XceedHexaEncodingFormat );
  365.       piHexaFormat->EndOfLineType = eEOLType;
  366.       piHexaFormat->MaxLineLength = dwMaxLineLength;
  367.       piEncode->EncodingFormat = IXceedEncodeDataPtr( piHexaFormat );
  368.     }
  369.     break;
  370.  
  371.     case emQuotedPrintable :
  372.     {
  373.       IXceedQuotedPrintableEncodingFormatPtr piQuotedPrintableFormat;
  374.       
  375.       piQuotedPrintableFormat.CreateInstance( CLSID_XceedQuotedPrintableEncodingFormat );
  376.       piQuotedPrintableFormat->EndOfLineType = eEOLType;
  377.       piQuotedPrintableFormat->MaxLineLength = dwMaxLineLength;
  378.       piEncode->EncodingFormat = IXceedEncodeDataPtr( piQuotedPrintableFormat );
  379.     }
  380.     break;
  381.  
  382.     case emBinHex :
  383.     {
  384.       // We open a handle on the input file which will be used
  385.       // to get the file's size.
  386.       HANDLE hFic = CreateFile( bstrInputFileName, GENERIC_READ, FILE_SHARE_WRITE & FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL );
  387.       
  388.       if( hFic != INVALID_HANDLE_VALUE )
  389.       {
  390.         IXceedBinHexEncodingFormatPtr piBinHexFormat;
  391.  
  392.         piBinHexFormat.CreateInstance( CLSID_XceedBinHexEncodingFormat );
  393.         piBinHexFormat->EndOfLineType = eEOLType;
  394.         piBinHexFormat->MaxLineLength = dwMaxLineLength;
  395.         // We want the output file to have BinHex formating
  396.         piBinHexFormat->IncludeHeaderFooter = TRUE;
  397.         // The DataForkLen is mandatory and must be set to the size
  398.         // of the data that will be encoded.
  399.         piBinHexFormat->HeaderDataForkLength = GetFileSize( hFic, NULL );
  400.         // The ResourceForkLen, used by MAC system, is not relevant 
  401.         // under a PC system. We set it to 0.
  402.         piBinHexFormat->HeaderResourceForkLength = 0;
  403.         piEncode->EncodingFormat = IXceedEncodeDataPtr( piBinHexFormat );
  404.  
  405.         CloseHandle( hFic );
  406.       }
  407.       else
  408.       {
  409.         printf( "Error opening the input filename\n\n" );
  410.         return false;
  411.       }
  412.     }
  413.     break;
  414.   }
  415.  
  416.   return true;
  417. }
  418.  
  419.  
  420. //
  421. // END_OF_FILE
  422. //
  423.