context: // DeflaterOutputStream.cs
  //
  // Copyright (C) 2001 Mike Krueger
  //
  // This file was translated from java, it was part of the GNU Classpath
  // Copyright (C) 2001 Free Software Foundation, Inc.
  //
  // This program is free software; you can redistribute it and/or
  // modify it under the terms of the GNU General Public License
  // as published by the Free Software Foundation; either version 2
  // of the License, or (at your option) any later version.
  //
  // This program is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  // GNU General Public License for more details.
  //
  // You should have received a copy of the GNU General Public License
  // along with this program; if not, write to the Free Software
  // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  //
  // Linking this library statically or dynamically with other modules is
  // making a combined work based on this library.  Thus, the terms and
  // conditions of the GNU General Public License cover the whole
  // combination.
  // 
  // As a special exception, the copyright holders of this library give you
  // permission to link this library with independent modules to produce an
  // executable, regardless of the license terms of these independent
  // modules, and to copy and distribute the resulting executable under
  // terms of your choice, provided that you also meet, for each linked
  // independent module, the terms and conditions of the license of that
  // module.  An independent module is a module which is not derived from
  // or based on this library.  If you modify this library, you may extend
  // this exception to your version of the library, but you are not
  // obligated to do so.  If you do not wish to do so, delete this
  // exception statement from your version.
  
  using System;
  using System.IO;
  using System.Security.Cryptography;
  
  #if !NETCF_1_0
  #endif
  
  namespace Fomm.SharpZipLib.Zip.Compression.Streams
  {
    /// <summary>
    ///   A special stream deflating or compressing the bytes that are
    ///   written to it.  It uses a Deflater to perform actual deflating.<br />
    ///   Authors of the original java version : Tom Tromey, Jochen Hoenicke
    /// </summary>
    internal class DeflaterOutputStream : Stream
    {
      #region Constructors
  
      /// <summary>
      ///   Creates a new DeflaterOutputStream with the given Deflater and
      ///   default buffer size.
      /// </summary>
      /// <param name="baseOutputStream">
      ///   the output stream where deflated output should be written.
      /// </param>
      /// <param name="deflater">
      ///   the underlying deflater.
      /// </param>
      public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater)
        : this(baseOutputStream, deflater, 512) {}
  
      /// <summary>
      ///   Creates a new DeflaterOutputStream with the given Deflater and
      ///   buffer size.
      /// </summary>
      /// <param name="baseOutputStream">
      ///   The output stream where deflated output is written.
      /// </param>
      /// <param name="deflater">
      ///   The underlying deflater to use
      /// </param>
      /// <param name="bufferSize">
      ///   The buffer size to use when deflating
      /// </param>
      /// <exception cref="ArgumentOutOfRangeException">
      ///   bufsize is less than or equal to zero.
      /// </exception>
      /// <exception cref="ArgumentException">
      ///   baseOutputStream does not support writing
      /// </exception>
      /// <exception cref="ArgumentNullException">
      ///   deflater instance is null
      /// </exception>
      public DeflaterOutputStream(Stream baseOutputStream, Deflater deflater, int bufferSize)
      {
        if (baseOutputStream == null)
        {
          throw new ArgumentNullException("baseOutputStream");
        }
  
        if (baseOutputStream.CanWrite == false)
        {
          throw new ArgumentException("Must support writing", "baseOutputStream");
        }
  
        if (deflater == null)
        {
          throw new ArgumentNullException("deflater");
        }
  
        if (bufferSize <= 0)
        {
          throw new ArgumentOutOfRangeException("bufferSize");
        }
  
        baseOutputStream_ = baseOutputStream;
        buffer_ = new byte[bufferSize];
        deflater_ = deflater;
      }
  
      #endregion
  
      #region Public API
  
      /// <summary>
      ///   Finishes the stream by calling finish() on the deflater.
      /// </summary>
      /// <exception cref="SharpZipBaseException">
      ///   Not all input is deflated
      /// </exception>
      public virtual void Finish()
      {
        deflater_.Finish();
        while (!deflater_.IsFinished)
        {
          var len = deflater_.Deflate(buffer_, 0, buffer_.Length);
          if (len <= 0)
          {
            break;
          }
  
  #if NETCF_1_0
          if ( keys != null ) {
  #else
          if (cryptoTransform_ != null)
          {
  #endif
            EncryptBlock(buffer_, 0, len);
          }
  
          baseOutputStream_.Write(buffer_, 0, len);
        }
  
        if (!deflater_.IsFinished)
        {
          throw new SharpZipBaseException("Can't deflate all input?");
        }
  
        baseOutputStream_.Flush();
  
  #if NETCF_1_0
        if ( keys != null ) {
          keys = null;
        }
  #else
        if (cryptoTransform_ != null)
        {
          cryptoTransform_.Dispose();
          cryptoTransform_ = null;
        }
  #endif
      }
  
      /// <summary>
      ///   Get/set flag indicating ownership of the underlying stream.
      ///   When the flag is true <see cref="Close"></see> will close the underlying stream also.
      /// </summary>
      public bool IsStreamOwner
      {
        set
        {
          isStreamOwner_ = value;
        }
      }
  
      /// <summary>
      ///   Allows client to determine if an entry can be patched after its added
      /// </summary>
      public bool CanPatchEntries
      {
        get
        {
          return baseOutputStream_.CanSeek;
        }
      }
  
      #endregion
  
      #region Encryption
  
  #if NETCF_1_0
      uint[] keys;
  #else
      private ICryptoTransform cryptoTransform_;
  #endif
  
      /// <summary>
      ///   Encrypt a block of data
      /// </summary>
      /// <param name="buffer">
      ///   Data to encrypt.  NOTE the original contents of the buffer are lost
      /// </param>
      /// <param name="offset">
      ///   Offset of first byte in buffer to encrypt
      /// </param>
      /// <param name="length">
      ///   Number of bytes in buffer to encrypt
      /// </param>
      protected void EncryptBlock(byte[] buffer, int offset, int length)
      {
  #if NETCF_1_0
        for (int i = offset; i < offset + length; ++i) {
          byte oldbyte = buffer[i];
          buffer[i] ^= EncryptByte();
          UpdateKeys(oldbyte);
        }
  #else
        cryptoTransform_.TransformBlock(buffer, offset, length, buffer, 0);
  #endif
      }
  
  #if NETCF_1_0
      
    /// <summary>
    /// Encrypt a single byte 
    /// </summary>
    /// <returns>
    /// The encrypted value
    /// </returns>
      protected byte EncryptByte()
      {
        uint temp = ((keys[2] & 0xFFFF) | 2);
  
gt:       return (byte)((temp * (temp ^ 1)) >> 8);