Bits.h

Go to the documentation of this file.
00001 /* @(#)root/zip:$Id: Bits.h 20882 2007-11-19 11:31:26Z rdm $ */
00002 /* Author: */
00003 /*
00004 
00005  Copyright (C) 1990-1993 Mark Adler, Richard B. Wales, Jean-loup Gailly,
00006  Kai Uwe Rommel and Igor Mandrichenko.
00007  For conditions of distribution and use, see copyright notice in zlib.h
00008 
00009 */
00010 /*
00011  * Changed for ROOT. Functions names have a R__ prepended to differentiate
00012  * them from function names in later versions of zlib.
00013  */
00014 
00015 #include "zlib.h"
00016 
00017 /*
00018  *  bits.c by Jean-loup Gailly and Kai Uwe Rommel.
00019  *
00020  *  This is a new version of im_bits.c originally written by Richard B. Wales
00021  *
00022  *  PURPOSE
00023  *
00024  *      Output variable-length bit strings. Compression can be done
00025  *      to a file or to memory.
00026  *
00027  *  DISCUSSION
00028  *
00029  *      The PKZIP "deflate" file format interprets compressed file data
00030  *      as a sequence of bits.  Multi-bit strings in the file may cross
00031  *      byte boundaries without restriction.
00032  *
00033  *      The first bit of each byte is the low-order bit.
00034  *
00035  *      The routines in this file allow a variable-length bit value to
00036  *      be output right-to-left (useful for literal values). For
00037  *      left-to-right output (useful for code strings from the tree routines),
00038  *      the bits must have been reversed first with R__bi_reverse().
00039  *
00040  *      For in-memory compression, the compressed bit stream goes directly
00041  *      into the requested output buffer. The input data is read in blocks
00042  *      by the R__mem_read() function. The buffer is limited to 64K on 16 bit
00043  *      machines.
00044  *
00045  *  INTERFACE
00046  *
00047  *      void R__bi_init (FILE *zipfile)
00048  *          Initialize the bit string routines.
00049  *
00050  *      void R__send_bits (int value, int length)
00051  *          Write out a bit string, taking the source bits right to
00052  *          left.
00053  *
00054  *      int R__bi_reverse (int value, int length)
00055  *          Reverse the bits of a bit string, taking the source bits left to
00056  *          right and emitting them right to left.
00057  *
00058  *      void R__bi_windup (void)
00059  *          Write out any remaining bits in an incomplete byte.
00060  *
00061  *      void R__copy_block(char far *buf, unsigned len, int header)
00062  *          Copy a stored block to the zip file, storing first the length and
00063  *          its one's complement if requested.
00064  *
00065  *      int R__seekable(void)
00066  *          Return true if the zip file can be seeked.
00067  *
00068  *      ulg R__memcompress (char *tgt, ulg tgtsize, char *src, ulg srcsize);
00069  *          Compress the source buffer src into the target buffer tgt.
00070  */
00071 
00072 /* #include "zip.h" */
00073 /* #include "ZIP.h" */
00074 
00075 /* extern ulg R__window_size; */ /* size of sliding window */
00076 
00077 
00078 /* ===========================================================================
00079  *  Prototypes for local functions
00080  */
00081 local int  R__mem_read     OF((char *buf, unsigned size));
00082 local void R__flush_outbuf OF((unsigned w, unsigned size));
00083 
00084 
00085 /* ===========================================================================
00086  * Local data used by the "bit string" routines.
00087  */
00088 local FILE *zfile; /* output zip file */
00089 
00090 local unsigned short bi_buf;
00091 /* Output buffer. bits are inserted starting at the bottom (least significant
00092  * bits).
00093  */
00094 
00095 #define Buf_size (8 * 2*sizeof(char))
00096 /* Number of bits used within bi_buf. (bi_buf might be implemented on
00097  * more than 16 bits on some systems.)
00098  */
00099 
00100 local int bi_valid;
00101 /* Number of valid bits in bi_buf.  All bits above the last valid bit
00102  * are always zero.
00103  */
00104 
00105 local char *in_buf, *out_buf;
00106 /* Current input and output buffers. in_buf is used only for in-memory
00107  * compression.
00108  */
00109 
00110 local unsigned in_offset, out_offset;
00111 /* Current offset in input and output buffers. in_offset is used only for
00112  * in-memory compression. On 16 bit machiens, the buffer is limited to 64K.
00113  */
00114 
00115 local unsigned in_size, out_size;
00116 /* Size of current input and output buffers */
00117 
00118 int (*R__read_buf) OF((char *buf, unsigned size)) = R__mem_read;
00119 /* Current input function. Set to R__mem_read for in-memory compression */
00120 
00121 #ifdef DEBUG
00122 ulg R__bits_sent;   /* bit length of the compressed data */
00123 #endif
00124 
00125 /* Output a 16 bit value to the bit stream, lower (oldest) byte first */
00126 #define PUTSHORT(w) \
00127 { if (out_offset < out_size-1) { \
00128     out_buf[out_offset++] = (char) ((w) & 0xff); \
00129     out_buf[out_offset++] = (char) ((ush)(w) >> 8); \
00130   } else { \
00131     R__flush_outbuf((w),2); \
00132   } \
00133 }
00134 
00135 #define PUTBYTE(b) \
00136 { if (out_offset < out_size) { \
00137     out_buf[out_offset++] = (char) (b); \
00138   } else { \
00139     R__flush_outbuf((b),1); \
00140   } \
00141 }
00142 
00143 
00144 /* ===========================================================================
00145    By default R__ZipMode = 1 (new zip compression algorithm.
00146    If R__ZipMode is set to 0 (via R__SetZipMode) the old zlib is used
00147  */
00148 int R__ZipMode = 1;
00149 
00150 /* ===========================================================================
00151  *  Prototypes for local functions
00152  */
00153 local int  R__mem_read     OF((char *b,    unsigned bsize));
00154 local void R__flush_outbuf OF((unsigned w, unsigned bytes));
00155 
00156 /* ===========================================================================
00157    Function to set the ZipMode
00158  */
00159 void R__SetZipMode(int mode)
00160 {
00161    R__ZipMode = mode;
00162 }
00163 
00164 /* ===========================================================================
00165  * Initialize the bit string routines.
00166  */
00167 void R__bi_init (FILE *zipfile)
00168     /* FILE *zipfile;   output zip file, NULL for in-memory compression */
00169 {
00170     zfile  = zipfile;
00171     bi_buf = 0;
00172     bi_valid = 0;
00173 #ifdef DEBUG
00174     R__bits_sent = 0L;
00175 #endif
00176 }
00177 
00178 /* ===========================================================================
00179  * Send a value on a given number of bits.
00180  * IN assertion: length <= 16 and value fits in length bits.
00181  */
00182 void R__send_bits(int value, int length)
00183     /* int value;   value to send */
00184     /* int length;  number of bits */
00185 {
00186 #ifdef DEBUG
00187     Tracevv((stderr," l %2d v %4x ", length, value));
00188     Assert(length > 0 && length <= 15, "invalid length");
00189     R__bits_sent += (ulg)length;
00190 #endif
00191     /* If not enough room in bi_buf, use (valid) bits from bi_buf and
00192      * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
00193      * unused bits in value.
00194      */
00195     if (bi_valid > (int)Buf_size - length) {
00196         bi_buf |= (value << bi_valid);
00197         PUTSHORT(bi_buf);
00198         bi_buf = (ush)value >> (Buf_size - bi_valid);
00199         bi_valid += length - Buf_size;
00200     } else {
00201         bi_buf |= value << bi_valid;
00202         bi_valid += length;
00203     }
00204 }
00205 
00206 /* ===========================================================================
00207  * Reverse the first len bits of a code, using straightforward code (a faster
00208  * method would use a table)
00209  * IN assertion: 1 <= len <= 15
00210  */
00211 unsigned R__bi_reverse(unsigned code, int len)
00212     /* unsigned code;  the value to invert */
00213     /* int len;        its bit length */
00214 {
00215     register unsigned res = 0;
00216     do {
00217         res |= code & 1;
00218         code >>= 1, res <<= 1;
00219     } while (--len > 0);
00220     return res >> 1;
00221 }
00222 
00223 /* ===========================================================================
00224  * Flush the current output buffer.
00225  */
00226 local void R__flush_outbuf(unsigned w, unsigned bytes)
00227     /* unsigned w;      value to flush */
00228     /* unsigned bytes;  number of bytes to flush (0, 1 or 2) */
00229 {
00230     R__error("output buffer too small for in-memory compression");
00231 
00232     /* Encrypt and write the output buffer: */
00233     out_offset = 0;
00234     if (bytes == 2) {
00235         PUTSHORT(w);
00236     } else if (bytes == 1) {
00237         out_buf[out_offset++] = (char) (w & 0xff);
00238     }
00239 }
00240 
00241 /* ===========================================================================
00242  * Write out any remaining bits in an incomplete byte.
00243  */
00244 void R__bi_windup()
00245 {
00246     if (bi_valid > 8) {
00247         PUTSHORT(bi_buf);
00248     } else if (bi_valid > 0) {
00249         PUTBYTE(bi_buf);
00250     }
00251     if (zfile != (FILE *) NULL) {
00252         R__flush_outbuf(0, 0);
00253     }
00254     bi_buf = 0;
00255     bi_valid = 0;
00256 #ifdef DEBUG
00257     R__bits_sent = (R__bits_sent+7) & ~7;
00258 #endif
00259 }
00260 
00261 /* ===========================================================================
00262  * Copy a stored block to the zip file, storing first the length and its
00263  * one's complement if requested.
00264  */
00265 void R__copy_block(char far *buf, unsigned len, int header)
00266     /* char far *buf;  the input data */
00267     /* unsigned len;   its length */
00268     /* int header;     true if block header must be written */
00269 {
00270     R__bi_windup();              /* align on byte boundary */
00271 
00272     if (header) {
00273         PUTSHORT((ush)len);
00274         PUTSHORT((ush)~len);
00275 #ifdef DEBUG
00276         R__bits_sent += 2*16;
00277 #endif
00278     }
00279     if (out_offset + len > out_size) {
00280         R__error("output buffer too small for in-memory compression");
00281         if (verbose) fprintf(stderr, "R__zip: out_offset=%d, len=%d, out_size=%d\n",out_offset,len,out_size);
00282     } else {
00283         memcpy(out_buf + out_offset, buf, len);
00284         out_offset += len;
00285     }
00286 #ifdef DEBUG
00287     R__bits_sent += (ulg)len<<3;
00288 #endif
00289 }
00290 
00291 
00292 /* ===========================================================================
00293  * Return true if the zip file can be seeked. This is used to check if
00294  * the local header can be re-rewritten. This function always returns
00295  * true for in-memory compression.
00296  * IN assertion: the local header has already been written (ftell() > 0).
00297  */
00298 int R__seekable()
00299 {
00300 #if 0
00301     return (zfile == NULL ||
00302             (fseek(zfile, -1L, SEEK_CUR) == 0 &&
00303              fseek(zfile,  1L, SEEK_CUR) == 0));
00304 #endif
00305 
00306     return (0);
00307 }
00308 
00309 /* ===========================================================================
00310  * In-memory compression. This version can be used only if the entire input
00311  * fits in one memory buffer. The compression is then done in a single
00312  * call of R__memcompress(). (An extension to allow repeated calls would be
00313  * possible but is not needed here.)
00314  * The first two bytes of the compressed output are set to a short with the
00315  * method used (DEFLATE or STORE). The following four bytes contain the CRC.
00316  * The values are stored in little-endian order on all machines.
00317  * This function returns the byte size of the compressed output, including
00318  * the first six bytes (method and crc).
00319  */
00320 
00321 ulg R__memcompress(char *tgt, ulg tgtsize, char *src, ulg srcsize)
00322     /* char *tgt, *src;        target and source buffers */
00323     /* ulg tgtsize, srcsize;   target and source sizes */
00324 {
00325     ush att      = (ush)UNKNOWN;
00326     ush flags    = 0;
00327     ulg crc      = 0;
00328     int method   = Z_DEFLATED;
00329 
00330     if (tgtsize <= 6L) R__error("target buffer too small");
00331 #if 0
00332     crc = updcrc((char *)NULL, 0);
00333     crc = updcrc(src, (extent) srcsize);
00334 #endif
00335     R__read_buf  = R__mem_read;
00336     in_buf    = src;
00337     in_size   = (unsigned)srcsize;
00338     in_offset = 0;
00339 
00340     out_buf    = tgt;
00341     out_size   = (unsigned)tgtsize;
00342     out_offset = 2 + 4;
00343     R__window_size = 0L;
00344 
00345     R__bi_init((FILE *)NULL);
00346     R__ct_init(&att, &method);
00347     R__lm_init((level != 0 ? level : 1), &flags);
00348     R__Deflate();
00349     R__window_size = 0L; /* was updated by lm_init() */
00350 
00351     /* For portability, force little-endian order on all machines: */
00352     tgt[0] = (char)(method & 0xff);
00353     tgt[1] = (char)((method >> 8) & 0xff);
00354     tgt[2] = (char)(crc & 0xff);
00355     tgt[3] = (char)((crc >> 8) & 0xff);
00356     tgt[4] = (char)((crc >> 16) & 0xff);
00357     tgt[5] = (char)((crc >> 24) & 0xff);
00358 
00359     return (ulg)out_offset;
00360 }
00361 
00362 /* ===========================================================================
00363  * In-memory read function. As opposed to file_read(), this function
00364  * does not perform end-of-line translation, and does not update the
00365  * crc and input size.
00366  *    Note that the size of the entire input buffer is an unsigned long,
00367  * but the size used in R__mem_read() is only an unsigned int. This makes a
00368  * difference on 16 bit machines. R__mem_read() may be called several
00369  * times for an in-memory compression.
00370  */
00371 local int R__mem_read(char *b, unsigned bsize)
00372 {
00373     if (in_offset < in_size) {
00374         ulg block_size = in_size - in_offset;
00375         if (block_size > (ulg)bsize) block_size = (ulg)bsize;
00376         memcpy(b, in_buf + in_offset, (unsigned)block_size);
00377         in_offset += (unsigned)block_size;
00378         return (int)block_size;
00379     } else {
00380         return 0; /* end of input */
00381     }
00382 }
00383 
00384 /***********************************************************************
00385  *                                                                     *
00386  * Name: R__zip                                      Date:    20.01.95 *
00387  * Author: E.Chernyaev (IHEP/Protvino)               Revised:          *
00388  *                                                                     *
00389  * Function: In memory ZIP compression                                 *
00390  *           It's a variant of R__memcompress adopted to be issued from*
00391  *           FORTRAN. Written for DELPHI collaboration (CERN)          *
00392  *                                                                     *
00393  * Input: cxlevel - compression level                                  *
00394  *        srcsize - size of input buffer                               *
00395  *        src     - input buffer                                       *
00396  *        tgtsize - size of target buffer                              *
00397  *                                                                     *
00398  * Output: tgt - target buffer (compressed)                            *
00399  *         irep - size of compressed data (0 - if error)               *
00400  *                                                                     *
00401  ***********************************************************************/
00402 #define HDRSIZE 9
00403 static  int error_flag;
00404 
00405 void R__zip(int cxlevel, int *srcsize, char *src, int *tgtsize, char *tgt, int *irep)
00406      /* int cxlevel;                      compression level */
00407      /* int  *srcsize, *tgtsize, *irep;   source and target sizes, replay */
00408      /* char *tgt, *src;                  source and target buffers */
00409 
00410 {
00411   int err;
00412   int method   = Z_DEFLATED;
00413 
00414   if (R__ZipMode != 0) {
00415     z_stream stream;
00416     *irep = 0;
00417 
00418     error_flag   = 0;
00419     if (*tgtsize <= HDRSIZE) R__error("target buffer too small");
00420     if (error_flag != 0) return;
00421     if (*srcsize > 0xffffff) R__error("source buffer too big");
00422     if (error_flag != 0) return;
00423 
00424 
00425     stream.next_in   = (Bytef*)src;
00426     stream.avail_in  = (uInt)(*srcsize);
00427 
00428     stream.next_out  = (Bytef*)(&tgt[HDRSIZE]);
00429     stream.avail_out = (uInt)(*tgtsize);
00430 
00431     stream.zalloc    = (alloc_func)0;
00432     stream.zfree     = (free_func)0;
00433     stream.opaque    = (voidpf)0;
00434 
00435     err = deflateInit(&stream, cxlevel);
00436     if (err != Z_OK) {
00437        printf("error %d in deflateInit (zlib)\n",err);
00438        return;
00439     }
00440 
00441     err = deflate(&stream, Z_FINISH);
00442     if (err != Z_STREAM_END) {
00443        deflateEnd(&stream);
00444        /* No need to print an error message. We simply abandon the compression
00445           the buffer cannot be compressed or compressed buffer would be larger than original buffer
00446           printf("error %d in deflate (zlib) is not = %d\n",err,Z_STREAM_END);
00447        */
00448        return;
00449     }
00450 
00451     err = deflateEnd(&stream);
00452 
00453     tgt[0] = 'Z';               /* Signature ZLib */
00454     tgt[1] = 'L';
00455     tgt[2] = (char) method;
00456 
00457     in_size   = (unsigned) (*srcsize);
00458     out_size  = stream.total_out;             /* compressed size */
00459     tgt[3] = (char)(out_size & 0xff);
00460     tgt[4] = (char)((out_size >> 8) & 0xff);
00461     tgt[5] = (char)((out_size >> 16) & 0xff);
00462 
00463     tgt[6] = (char)(in_size & 0xff);         /* decompressed size */
00464     tgt[7] = (char)((in_size >> 8) & 0xff);
00465     tgt[8] = (char)((in_size >> 16) & 0xff);
00466 
00467     *irep = stream.total_out + HDRSIZE;
00468   } else {
00469     ush att      = (ush)UNKNOWN;
00470     ush flags    = 0;
00471     level        = cxlevel;
00472 
00473     *irep        = 0;
00474     error_flag   = 0;
00475     if (*tgtsize <= HDRSIZE) R__error("target buffer too small");
00476     if (error_flag != 0) return;
00477     if (*srcsize > 0xffffff) R__error("source buffer too big");
00478     if (error_flag != 0) return;
00479 
00480     R__read_buf  = R__mem_read;
00481     in_buf    = src;
00482     in_size   = (unsigned) (*srcsize);
00483     in_offset = 0;
00484 
00485     out_buf     = tgt;
00486     out_size    = (unsigned) (*tgtsize);
00487     out_offset  = HDRSIZE;
00488     R__window_size = 0L;
00489 
00490     R__bi_init((FILE *)NULL);      /* initialize bit routines */
00491     if (error_flag != 0) return;
00492     R__ct_init(&att, &method);     /* initialize tree routines */
00493     if (error_flag != 0) return;
00494     R__lm_init(level, &flags);     /* initialize compression */
00495     if (error_flag != 0) return;
00496     R__Deflate();                  /* compress data */
00497     if (error_flag != 0) return;
00498 
00499     tgt[0] = 'C';               /* Signature 'C'-Chernyaev, 'S'-Smirnov */
00500     tgt[1] = 'S';
00501     tgt[2] = (char) method;
00502 
00503     out_size  = out_offset - HDRSIZE;         /* compressed size */
00504     tgt[3] = (char)(out_size & 0xff);
00505     tgt[4] = (char)((out_size >> 8) & 0xff);
00506     tgt[5] = (char)((out_size >> 16) & 0xff);
00507 
00508     tgt[6] = (char)(in_size & 0xff);         /* decompressed size */
00509     tgt[7] = (char)((in_size >> 8) & 0xff);
00510     tgt[8] = (char)((in_size >> 16) & 0xff);
00511 
00512     *irep     = out_offset;
00513     return;
00514   }
00515 }
00516 
00517 void R__error(char *msg)
00518 {
00519   if (verbose) fprintf(stderr,"R__zip: %s\n",msg);
00520   error_flag = 1;
00521 }
00522 

Generated on Tue Jul 5 14:12:04 2011 for ROOT_528-00b_version by  doxygen 1.5.1