Mes documents/Visual Studio 2005/Projects/TES4ModTranslator/TES4ModTranslator/Zip/Compression/Deflater.cs

Go to the documentation of this file.
00001 // Deflater.cs
00002 //
00003 // Copyright (C) 2001 Mike Krueger
00004 // Copyright (C) 2004 John Reilly
00005 //
00006 // This file was translated from java, it was part of the GNU Classpath
00007 // Copyright (C) 2001 Free Software Foundation, Inc.
00008 //
00009 // This program is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU General Public License
00011 // as published by the Free Software Foundation; either version 2
00012 // of the License, or (at your option) any later version.
00013 //
00014 // This program 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
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with this program; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 //
00023 // Linking this library statically or dynamically with other modules is
00024 // making a combined work based on this library.  Thus, the terms and
00025 // conditions of the GNU General Public License cover the whole
00026 // combination.
00027 // 
00028 // As a special exception, the copyright holders of this library give you
00029 // permission to link this library with independent modules to produce an
00030 // executable, regardless of the license terms of these independent
00031 // modules, and to copy and distribute the resulting executable under
00032 // terms of your choice, provided that you also meet, for each linked
00033 // independent module, the terms and conditions of the license of that
00034 // module.  An independent module is a module which is not derived from
00035 // or based on this library.  If you modify this library, you may extend
00036 // this exception to your version of the library, but you are not
00037 // obligated to do so.  If you do not wish to do so, delete this
00038 // exception statement from your version.
00039 
00040 using System;
00041 
00042 namespace ICSharpCode.SharpZipLib.Zip.Compression
00043 {
00044         
00055         public class Deflater
00056         {
00061                 public static  int BEST_COMPRESSION = 9;
00062                 
00066                 public static  int BEST_SPEED = 1;
00067                 
00071                 public static  int DEFAULT_COMPRESSION = -1;
00072                 
00076                 public static  int NO_COMPRESSION = 0;
00077                                 
00082                 public static  int DEFLATED = 8;
00083                 
00084                 /*
00085                 * The Deflater can do the following state transitions:
00086                         *
00087                         * (1) -> INIT_STATE   ----> INIT_FINISHING_STATE ---.
00088                         *        /  | (2)      (5)                         |
00089                         *       /   v          (5)                         |
00090                         *   (3)| SETDICT_STATE ---> SETDICT_FINISHING_STATE |(3)
00091                         *       \   | (3)                 |        ,-------'
00092                         *        |  |                     | (3)   /
00093                         *        v  v          (5)        v      v
00094                         * (1) -> BUSY_STATE   ----> FINISHING_STATE
00095                         *                                | (6)
00096                         *                                v
00097                         *                           FINISHED_STATE
00098                         *    \_____________________________________/
00099                         *          | (7)
00100                         *          v
00101                         *        CLOSED_STATE
00102                         *
00103                         * (1) If we should produce a header we start in INIT_STATE, otherwise
00104                         *     we start in BUSY_STATE.
00105                         * (2) A dictionary may be set only when we are in INIT_STATE, then
00106                         *     we change the state as indicated.
00107                         * (3) Whether a dictionary is set or not, on the first call of deflate
00108                         *     we change to BUSY_STATE.
00109                         * (4) -- intentionally left blank -- :)
00110                         * (5) FINISHING_STATE is entered, when flush() is called to indicate that
00111                         *     there is no more INPUT.  There are also states indicating, that
00112                         *     the header wasn't written yet.
00113                         * (6) FINISHED_STATE is entered, when everything has been flushed to the
00114                         *     internal pending output buffer.
00115                         * (7) At any time (7)
00116                         *
00117                         */
00118                         
00119                 private static  int IS_SETDICT              = 0x01;
00120                 private static  int IS_FLUSHING             = 0x04;
00121                 private static  int IS_FINISHING            = 0x08;
00122                 
00123                 private static  int INIT_STATE              = 0x00;
00124                 private static  int SETDICT_STATE           = 0x01;
00125                 //              private static  int INIT_FINISHING_STATE    = 0x08;
00126                 //              private static  int SETDICT_FINISHING_STATE = 0x09;
00127                 private static  int BUSY_STATE              = 0x10;
00128                 private static  int FLUSHING_STATE          = 0x14;
00129                 private static  int FINISHING_STATE         = 0x1c;
00130                 private static  int FINISHED_STATE          = 0x1e;
00131                 private static  int CLOSED_STATE            = 0x7f;
00132                 
00136                 private int level;
00137                 
00141                 private bool noZlibHeaderOrFooter;
00142                 
00146                 private int state;
00147                 
00151                 private long totalOut;
00152                 
00156                 private DeflaterPending pending;
00157                 
00161                 private DeflaterEngine engine;
00162                 
00166                 public Deflater() : this(DEFAULT_COMPRESSION, false)
00167                 {
00168                         
00169                 }
00170                 
00179                 public Deflater(int lvl) : this(lvl, false)
00180                 {
00181                         
00182                 }
00183                 
00197                 public Deflater(int level, bool noZlibHeaderOrFooter)
00198                 {
00199                         if (level == DEFAULT_COMPRESSION) {
00200                                 level = 6;
00201                         } else if (level < NO_COMPRESSION || level > BEST_COMPRESSION) {
00202                                 throw new ArgumentOutOfRangeException("level");
00203                         }
00204                         
00205                         pending = new DeflaterPending();
00206                         engine = new DeflaterEngine(pending);
00207                         this.noZlibHeaderOrFooter = noZlibHeaderOrFooter;
00208                         SetStrategy(DeflateStrategy.Default);
00209                         SetLevel(level);
00210                         Reset();
00211                 }
00212                 
00213                 
00219                 public void Reset()
00220                 {
00221                         state = (noZlibHeaderOrFooter ? BUSY_STATE : INIT_STATE);
00222                         totalOut = 0;
00223                         pending.Reset();
00224                         engine.Reset();
00225                 }
00226                 
00230                 public int Adler {
00231                         get {
00232                                 return engine.Adler;
00233                         }
00234                 }
00235                 
00239                 public int TotalIn {
00240                         get {
00241                                 return engine.TotalIn;
00242                         }
00243                 }
00244                 
00248                 public long TotalOut {
00249                         get {
00250                                 return totalOut;
00251                         }
00252                 }
00253                 
00261                 public void Flush() 
00262                 {
00263                         state |= IS_FLUSHING;
00264                 }
00265                 
00271                 public void Finish() 
00272                 {
00273                         state |= IS_FLUSHING | IS_FINISHING;
00274                 }
00275                 
00280                 public bool IsFinished {
00281                         get {
00282                                 return state == FINISHED_STATE && pending.IsFlushed;
00283                         }
00284                 }
00285                 
00292                 public bool IsNeedingInput {
00293                         get {
00294                                 return engine.NeedsInput();
00295                         }
00296                 }
00297                 
00313                 public void SetInput(byte[] input)
00314                 {
00315                         SetInput(input, 0, input.Length);
00316                 }
00317                 
00336                 public void SetInput(byte[] input, int off, int len)
00337                 {
00338                         if ((state & IS_FINISHING) != 0) {
00339                                 throw new InvalidOperationException("finish()/end() already called");
00340                         }
00341                         engine.SetInput(input, off, len);
00342                 }
00343                 
00353                 public void SetLevel(int lvl)
00354                 {
00355                         if (lvl == DEFAULT_COMPRESSION) {
00356                                 lvl = 6;
00357                         } else if (lvl < NO_COMPRESSION || lvl > BEST_COMPRESSION) {
00358                                 throw new ArgumentOutOfRangeException("lvl");
00359                         }
00360                         
00361                         if (level != lvl) {
00362                                 level = lvl;
00363                                 engine.SetLevel(lvl);
00364                         }
00365                 }
00366                 
00371                 public int GetLevel() {
00372                         return level;
00373                 }
00374                 
00384                 public void SetStrategy(DeflateStrategy strategy)
00385                 {
00386                         engine.Strategy = strategy;
00387                 }
00388                 
00399                 public int Deflate(byte[] output)
00400                 {
00401                         return Deflate(output, 0, output.Length);
00402                 }
00403                 
00426                 public int Deflate(byte[] output, int offset, int length)
00427                 {
00428                         int origLength = length;
00429                         
00430                         if (state == CLOSED_STATE) {
00431                                 throw new InvalidOperationException("Deflater closed");
00432                         }
00433                         
00434                         if (state < BUSY_STATE) {
00435                                 /* output header */
00436                                 int header = (DEFLATED +
00437                                         ((DeflaterConstants.MAX_WBITS - 8) << 4)) << 8;
00438                                 int level_flags = (level - 1) >> 1;
00439                                 if (level_flags < 0 || level_flags > 3) {
00440                                         level_flags = 3;
00441                                 }
00442                                 header |= level_flags << 6;
00443                                 if ((state & IS_SETDICT) != 0) {
00444                                         /* Dictionary was set */
00445                                         header |= DeflaterConstants.PRESET_DICT;
00446                                 }
00447                                 header += 31 - (header % 31);
00448                                 
00449                                 
00450                                 pending.WriteShortMSB(header);
00451                                 if ((state & IS_SETDICT) != 0) {
00452                                         int chksum = engine.Adler;
00453                                         engine.ResetAdler();
00454                                         pending.WriteShortMSB(chksum >> 16);
00455                                         pending.WriteShortMSB(chksum & 0xffff);
00456                                 }
00457                                 
00458                                 state = BUSY_STATE | (state & (IS_FLUSHING | IS_FINISHING));
00459                         }
00460                         
00461                         for (;;) {
00462                                 int count = pending.Flush(output, offset, length);
00463                                 offset   += count;
00464                                 totalOut += count;
00465                                 length   -= count;
00466                                 
00467                                 if (length == 0 || state == FINISHED_STATE) {
00468                                         break;
00469                                 }
00470                                 
00471                                 if (!engine.Deflate((state & IS_FLUSHING) != 0, (state & IS_FINISHING) != 0)) {
00472                                         if (state == BUSY_STATE) {
00473                                                 /* We need more input now */
00474                                                 return origLength - length;
00475                                         } else if (state == FLUSHING_STATE) {
00476                                                 if (level != NO_COMPRESSION) {
00477                                                         /* We have to supply some lookahead.  8 bit lookahead
00478                                                          * is needed by the zlib inflater, and we must fill
00479                                                          * the next byte, so that all bits are flushed.
00480                                                          */
00481                                                         int neededbits = 8 + ((-pending.BitCount) & 7);
00482                                                         while (neededbits > 0) {
00483                                                                 /* write a static tree block consisting solely of
00484                                                                  * an EOF:
00485                                                                  */
00486                                                                 pending.WriteBits(2, 10);
00487                                                                 neededbits -= 10;
00488                                                         }
00489                                                 }
00490                                                 state = BUSY_STATE;
00491                                         } else if (state == FINISHING_STATE) {
00492                                                 pending.AlignToByte();
00493 
00494                                                 // Compressed data is complete.  Write footer information if required.
00495                                                 if (!noZlibHeaderOrFooter) {
00496                                                         int adler = engine.Adler;
00497                                                         pending.WriteShortMSB(adler >> 16);
00498                                                         pending.WriteShortMSB(adler & 0xffff);
00499                                                 }
00500                                                 state = FINISHED_STATE;
00501                                         }
00502                                 }
00503                         }
00504                         return origLength - length;
00505                 }
00506                 
00517                 public void SetDictionary(byte[] dict)
00518                 {
00519                         SetDictionary(dict, 0, dict.Length);
00520                 }
00521                 
00542                 public void SetDictionary(byte[] dict, int offset, int length)
00543                 {
00544                         if (state != INIT_STATE) {
00545                                 throw new InvalidOperationException();
00546                         }
00547                         
00548                         state = SETDICT_STATE;
00549                         engine.SetDictionary(dict, offset, length);
00550                 }
00551         }
00552 }

Generated on Fri Jun 23 21:50:04 2006 for OblivionModTranslator by  doxygen 1.4.6-NO