BESUncompressZ.cc

Go to the documentation of this file.
00001 // BESUncompressZ.c
00002 
00003 // This file is part of bes, A C++ back-end server implementation framework
00004 // for the OPeNDAP Data Access Protocol.
00005 
00006 // Copyright (c) 2004,2005 University Corporation for Atmospheric Research
00007 // Author:
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 // 
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 // 
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact University Corporation for Atmospheric Research at
00024 // 3080 Center Green Drive, Boulder, CO 80301
00025  
00026 // (c) COPYRIGHT University Corporation for Atmostpheric Research 2004-2005
00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
00028 //
00029 // Authors:
00030 //      dnadeau     Denis Nadeau <dnadeau@pop600.gsfc.nasa.gov>
00031 
00032 
00033 #include <stdlib.h>
00034 #include <unistd.h>
00035 #include <errno.h>
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <fcntl.h>
00039 
00040 
00041 #include "BESUncompressZ.h"
00042 #include "BESContainerStorageException.h"
00043 #include "BESDebug.h"
00044 
00045 
00052 string
00053 BESUncompressZ::uncompress( const string &src, const string &target )
00054 {
00055 
00056 /* -------------------------------------------------------------------- */
00057 /*      Open the file to be read                                        */
00058 /* -------------------------------------------------------------------- */
00059 
00060     int srcFile ;
00061     srcFile=open( src.c_str(), O_RDONLY ) ;
00062     BESDEBUG( "bes", "BESUncompressZ::uncompress - src=" << src.c_str() << endl ) ;
00063     if( srcFile == -1 )
00064     {
00065         string err = "Could not open the compressed file " + src ;
00066         throw BESContainerStorageException( err, __FILE__, __LINE__ ) ;
00067     }
00068 
00069 /* -------------------------------------------------------------------- */
00070 /*      Open Output file                                                */
00071 /* -------------------------------------------------------------------- */
00072     int destFile ;
00073     destFile = open( target.c_str(), O_WRONLY | O_CREAT | O_TRUNC
00074                      , S_IRUSR | S_IWUSR ) ;
00075     BESDEBUG( "bes", "BESUncompressZ::uncompress - target=" 
00076               << target.c_str() 
00077               << endl ) ;
00078 
00079     if( destFile == -1)
00080     {
00081         char *serr = strerror( errno ) ;
00082         string err = "Unable to create the uncompressed file "
00083                      + target + ": " ;
00084         BESDEBUG( "bes", "BESUncompressZ::uncompress - cant open file" 
00085                   << errno 
00086                   << endl);
00087         
00088         if( serr )
00089         {
00090             err.append( serr ) ;
00091         }
00092         else
00093         {
00094             err.append( "unknown error occurred" ) ;
00095         }
00096         close( srcFile ) ;
00097         throw BESContainerStorageException( err, __FILE__, __LINE__ ) ;
00098     }
00099 
00100 
00101 /* ==================================================================== */
00102 /*      Start decompress LZW inspired from ncompress-4.2.4.orig         */
00103 /* ==================================================================== */
00104 
00105     BESDEBUG( "bes", "BESUncompressZ::uncompress - start decompress" << endl);
00106 
00107 #define FIRSTBYTE       (unsigned char)'\037'/* First byte of compressed file*/
00108 #define SECONDBYTE      (unsigned char)'\235'/* Second byte of compressed file*/
00109 #define FIRST           257
00110 #define BIT_MASK        0x1f
00111 #define BLOCK_MODE      0x80    
00112 #define MAXCODE(n)      (1L << (n))
00113 #define BITS            16      
00114 #define INIT_BITS       9       
00115 #define CLEAR           256             /* table clear output code*/
00116 #define HBITS           17                      /* 50% occupancy */
00117 #define HSIZE           (1<<HBITS)
00118 #define HMASK           (HSIZE-1)
00119 #define BITS            16
00120 #define de_stack        ((unsigned char *)&(htab[HSIZE-1]))
00121 #define BYTEORDER       0000
00122 #define NOALLIGN        0
00123 
00124     unsigned char       htab[HSIZE*4];
00125     unsigned short      codetab[HSIZE];
00126 
00127     int block_mode = BLOCK_MODE; 
00128     int maxbits = BITS;         
00129     unsigned char       inbuf[BUFSIZ+64];       /* Input buffer */
00130     unsigned char       outbuf[BUFSIZ+2048];    /* Output buffer */
00131     unsigned char       *stackp;
00132     long int             code;
00133     int                  finchar;
00134     long int             oldcode;
00135     long int             incode;
00136     int                  inbits;
00137     int                  posbits;
00138     int                  outpos;
00139     int                  insize;
00140     int                  bitmask;
00141     long int             free_ent;
00142     long int             maxcode;
00143     long int             maxmaxcode;
00144     int                  n_bits;
00145     int                   rsize;
00146 
00147     insize = 0;
00148     
00149     BESDEBUG( "bes", "BESUncompressZ::uncompress - read file" << endl);     
00150 /* -------------------------------------------------------------------- */
00151 /*       Verify if the .Z file start with 0x1f and 0x9d                 */
00152 /* -------------------------------------------------------------------- */
00153     while( insize < 3 && (rsize = read(srcFile, inbuf+insize, BUFSIZ)) > 0) {
00154         insize += rsize;
00155     }
00156     BESDEBUG( "bes", "BESUncompressZ::uncompress - insize: " << insize << endl); 
00157 
00158 /* -------------------------------------------------------------------- */
00159 /*       Do we have compressed file?                                    */
00160 /* -------------------------------------------------------------------- */
00161     if( (insize < 3) || (inbuf[0] != FIRSTBYTE) || (inbuf[1] != SECONDBYTE)) {
00162         BESDEBUG( "bes", "BESUncompressZ::uncompress - in here!!!!! " << endl);     
00163         if( rsize < 0) {
00164             string err = "Could not read file ";
00165             err += src.c_str() ;
00166             throw BESContainerStorageException( err, __FILE__, __LINE__ ) ;
00167         }
00168         
00169         if( insize > 0)  {
00170             string err = src.c_str();
00171             err += ": not in compressed format";
00172             throw BESContainerStorageException( err, __FILE__, __LINE__ ) ;
00173         }
00174         
00175         string err = "unknown error";
00176         throw BESContainerStorageException( err, __FILE__, __LINE__ ) ;
00177 
00178     }
00179 
00180 /* -------------------------------------------------------------------- */
00181 /*       handle compression                                             */
00182 /* -------------------------------------------------------------------- */
00183     maxbits = inbuf[2] & BIT_MASK;
00184     block_mode = inbuf[2] & BLOCK_MODE;
00185     maxmaxcode = MAXCODE(maxbits);      
00186     
00187     if( maxbits > BITS ) {
00188         string err = src.c_str();
00189         err += ": compressed with " ;
00190         err += maxbits ;
00191         err += " bits, can only handle";
00192         err += BITS;
00193         throw BESContainerStorageException( err, __FILE__, __LINE__ ) ;
00194     }
00195 
00196     maxcode = MAXCODE(n_bits = INIT_BITS)-1;
00197     bitmask = (1<<n_bits)-1;
00198     oldcode = -1;
00199     finchar = 0;
00200     outpos = 0;
00201     posbits = 3<<3;
00202 
00203     free_ent = ((block_mode) ? FIRST : 256);
00204 
00205     BESDEBUG( "bes", "BESUncompressZ::uncompress - entering loop" << endl);
00206    
00207     memset(codetab, 0, 256);
00208     
00209     for (code = 255 ; code >= 0 ; --code){
00210         ((unsigned char *)(htab))[code] = (unsigned char) code;
00211     }
00212 
00213     do
00214         {
00215         resetbuf:       ;
00216             {
00217                 int     i;
00218                 int     e;
00219                 int     o;
00220                 
00221                 e = insize - ( o = ( posbits >> 3 ) );
00222                 
00223                 for (i = 0 ; i < e ; ++i)
00224                     inbuf[i] = inbuf[i+o];
00225                 
00226                 insize = e;
00227                 posbits = 0;
00228             }
00229                     
00230             if( insize < sizeof( inbuf ) - BUFSIZ ) {
00231                 if( ( rsize = read( srcFile, inbuf + insize, BUFSIZ )) < 0) {
00232                     string err = "Could not read file ";
00233                     err += src.c_str() ;
00234                     throw BESContainerStorageException( err, 
00235                                                         __FILE__, 
00236                                                         __LINE__ ) ;
00237                 }
00238                 
00239                 insize += rsize;
00240             }
00241                     
00242             inbits = ( ( rsize > 0 ) ? ( insize - insize % n_bits ) << 3 : 
00243                        ( insize << 3 ) - ( n_bits - 1 ));
00244 
00245             while( inbits > posbits ){
00246                 if( free_ent > maxcode ) {
00247                     posbits = ( ( posbits-1 ) + 
00248                                 ( ( n_bits << 3 ) - 
00249                                   ( posbits-1 +  ( n_bits << 3)) % 
00250                                   ( n_bits<<3 ) ) 
00251                                 );
00252                                     
00253                     ++n_bits;
00254                     if( n_bits == maxbits)
00255                         maxcode = maxmaxcode;
00256                     else
00257                         maxcode = MAXCODE(n_bits)-1;
00258                     
00259                     bitmask = (1<<n_bits)-1;
00260                     goto resetbuf;
00261                 }
00262                 
00263                 unsigned char*p = &inbuf[posbits>>3];           
00264                 
00265                 code = ( ( ( (long) ( p[0] ) ) | ( ( long )( p[1] ) << 8 ) |
00266                            ( (long) ( p[2] ) << 16 ) ) >> ( posbits & 0x7 ) ) &
00267                     bitmask; 
00268                 
00269                 posbits += n_bits;                                      
00270 
00271                 
00272                 if( oldcode == -1) {
00273                     if( code >= 256) {
00274                         string err = "oldcode:-1 code: ";
00275                         err += code ;
00276                         err += " !!!! uncompress: corrupt input!!!";
00277                         throw BESContainerStorageException( err, 
00278                                                             __FILE__, 
00279                                                             __LINE__ ) ;
00280                     }
00281                     outbuf[outpos++] = (unsigned char)(finchar = 
00282                                                    (int)(oldcode = code));
00283                     continue;
00284                 }
00285 
00286                 /* Clear */
00287                 if( code == CLEAR && block_mode) {
00288                     memset(codetab, 0, 256);
00289                     free_ent = FIRST - 1;
00290                     posbits = ( ( posbits - 1 ) + 
00291                                 ( ( n_bits << 3 ) -
00292                                   ( posbits - 1 + ( n_bits << 3 ) ) % 
00293                                   ( n_bits<<3) ) );
00294                     maxcode = MAXCODE( n_bits = INIT_BITS ) - 1;
00295                     bitmask = ( 1 << n_bits )-1;
00296                     goto resetbuf;
00297                 }
00298                                 
00299                 incode = code;
00300                 stackp = de_stack;
00301 
00302                 /* Special case for KwKwK string.*/
00303                 if( code >= free_ent ) {
00304                     if( code > free_ent ) {
00305                         unsigned char   *p;
00306                         posbits -= n_bits;
00307                         p = &inbuf[posbits>>3];
00308                         
00309                         string err = "uncompress: corrupt input";
00310                         throw BESContainerStorageException( err, 
00311                                                             __FILE__, 
00312                                                             __LINE__ ) ;
00313                     }
00314                     
00315                     *--stackp = ( unsigned char )finchar;
00316                     code = oldcode;
00317                 }
00318                 
00319                 /* Generate output characters in reverse order */
00320                 while( (unsigned long)code >= (unsigned long)256) { 
00321                     *--stackp = htab[code];
00322                     code = codetab[code];
00323                 }
00324                                 
00325                 *--stackp = (unsigned char)(finchar = htab[code]);
00326                                 
00327                 /* And put them out in forward order */         
00328                 {
00329                     int i;
00330                     if( outpos+(i = (de_stack-stackp)) >= BUFSIZ) {
00331                         do  {
00332 
00333                             if( i > BUFSIZ-outpos) {
00334                                 i = BUFSIZ-outpos;      
00335                             }
00336             
00337                             if( i > 0) {
00338                                 memcpy(outbuf+outpos, stackp, i);
00339                                 outpos += i;
00340                             }
00341                                     
00342                             if( outpos >= BUFSIZ) {
00343                                 if( write(destFile, outbuf,outpos) != outpos) {
00344                                     string err = "uncompress: write eror";
00345                                     throw BESContainerStorageException( err, 
00346                                                         __FILE__, 
00347                                                         __LINE__ ) ;
00348                                 }               
00349                                 outpos = 0;
00350                             }
00351                             stackp+= i;
00352                         }
00353                         while( (i = (de_stack-stackp)) > 0) ; /* de-stack */
00354                     }
00355                     else {
00356                         memcpy(outbuf+outpos, stackp, i);
00357                         outpos += i;
00358                     }
00359                 }
00360                 /* Generate the new entry. */
00361                 if( (code = free_ent) < maxmaxcode)  {
00362                     codetab[code] = (unsigned short)oldcode;
00363                     htab[code] = (unsigned char)finchar;
00364                     free_ent = code+1;
00365                 } 
00366                 
00367                 oldcode = incode;       /* Remember previous code.      */
00368             }
00369         }
00370 
00371     while( rsize > 0); /* end of do */
00372     
00373     if( outpos > 0 && write(destFile, outbuf, outpos) != outpos) {
00374         string err = "uncompress: write eror";
00375         throw BESContainerStorageException( err, 
00376                                             __FILE__, 
00377                                             __LINE__ ) ;
00378     }
00379     BESDEBUG( "bes", "BESUncompressZ::uncompress - end decompres" << endl);
00380     return target.c_str();
00381     
00382 }
00383 

Generated on Fri Nov 30 12:06:48 2007 for OPeNDAP Back End Server (BES) by  doxygen 1.5.1