context: // PendingBuffer.cs
  //
  // Copyright (C) 2001 Mike Krueger
  // Copyright (C) 2004 John Reilly
  //
  // 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;
  
  namespace Fomm.SharpZipLib.Zip.Compression
  {
    /// <summary>
    ///   This class is general purpose class for writing data to a buffer.
    ///   It allows you to write bits as well as bytes
    ///   Based on DeflaterPending.java
    ///   author of the original java version : Jochen Hoenicke
    /// </summary>
    internal class PendingBuffer
    {
      #region Instance Fields
  
      /// <summary>
      ///   Internal work buffer
      /// </summary>
      private byte[] buffer_;
  
      private int start;
      private int end;
  
      private uint bits;
  
      #endregion
  
      #region Constructors
  
      /// <summary>
      ///   construct instance using default buffer size of 4096
      /// </summary>
      public PendingBuffer() : this(4096) {}
  
      /// <summary>
      ///   construct instance using specified buffer size
      /// </summary>
      /// <param name="bufferSize">
      ///   size to use for internal buffer
      /// </param>
      public PendingBuffer(int bufferSize)
      {
        buffer_ = new byte[bufferSize];
      }
  
      #endregion
  
      /// <summary>
      ///   Clear internal state/buffers
      /// </summary>
      public void Reset()
      {
        start = end = BitCount = 0;
      }
  
      /// <summary>
      ///   Write a short value to buffer LSB first
      /// </summary>
      /// <param name="value">
      ///   The value to write.
      /// </param>
      public void WriteShort(int value)
      {
  #if DebugDeflation
        if (DeflaterConstants.DEBUGGING && (start != 0) )
        {
          throw new SharpZipBaseException("Debug check: start != 0");
        }
  #endif
        buffer_[end++] = unchecked((byte) value);
        buffer_[end++] = unchecked((byte) (value >> 8));
      }
  
      /// <summary>
      ///   Write a block of data to buffer
      /// </summary>
      /// <param name="block">data to write</param>
      /// <param name="offset">offset of first byte to write</param>
      /// <param name="length">number of bytes to write</param>
      public void WriteBlock(byte[] block, int offset, int length)
      {
  #if DebugDeflation
        if (DeflaterConstants.DEBUGGING && (start != 0) ) 
        {
          throw new SharpZipBaseException("Debug check: start != 0");
        }
  #endif
        Array.Copy(block, offset, buffer_, end, length);
        end += length;
      }
  
      /// <summary>
      ///   The number of bits written to the buffer
      /// </summary>
      public int BitCount { get; private set; }
  
      /// <summary>
      ///   Align internal buffer on a byte boundary
      /// </summary>
      public void AlignToByte()
      {
  #if DebugDeflation
        if (DeflaterConstants.DEBUGGING && (start != 0) ) 
        {
          throw new SharpZipBaseException("Debug check: start != 0");
        }
  #endif
        if (BitCount > 0)
        {
          buffer_[end++] = unchecked((byte) bits);
          if (BitCount > 8)
          {
            buffer_[end++] = unchecked((byte) (bits >> 8));
          }
        }
        bits = 0;
        BitCount = 0;
      }
  
      /// <summary>
      ///   Write bits to internal buffer
      /// </summary>
      /// <param name="b">source of bits</param>
      /// <param name="count">number of bits to write</param>
      public void WriteBits(int b, int count)
      {
  #if DebugDeflation
        if (DeflaterConstants.DEBUGGING && (start != 0) ) 
        {
          throw new SharpZipBaseException("Debug check: start != 0");
        }
  
        //      if (DeflaterConstants.DEBUGGING) {
        //        //Console.WriteLine("writeBits("+b+","+count+")");
        //      }
  #endif
        bits |= (uint) (b << BitCount);
        BitCount += count;
        if (BitCount >= 16)
        {
          buffer_[end++] = unchecked((byte) bits);
          buffer_[end++] = unchecked((byte) (bits >> 8));
          bits >>= 16;
          BitCount -= 16;
        }
      }
  
      /// <summary>
      ///   Write a short value to internal buffer most significant byte first
      /// </summary>
      /// <param name="s">value to write</param>
      public void WriteShortMSB(int s)
      {
  #if DebugDeflation
        if (DeflaterConstants.DEBUGGING && (start != 0) ) 
        {
          throw new SharpZipBaseException("Debug check: start != 0");
        }
  #endif
        buffer_[end++] = unchecked((byte) (s >> 8));
        buffer_[end++] = unchecked((byte) s);
      }
  
      /// <summary>
      ///   Indicates if buffer has been flushed
      /// </summary>
      public bool IsFlushed
      {
        get
        {
          return end == 0;
        }
      }
  
      /// <summary>
      ///   Flushes the pending buffer into the given output array.  If the
      ///   output array is to small, only a partial flush is done.
      /// </summary>
      /// <param name="output">The output array.</param>
      /// <param name="offset">The offset into output array.</param>
      /// <param name="length">The maximum number of bytes to store.</param>
      /// <returns>The number of bytes flushed.</returns>
      public int Flush(byte[] output, int offset, int length)
      {
        if (BitCount >= 8)
        {
          buffer_[end++] = unchecked((byte) bits);
          bits >>= 8;
          BitCount -= 8;
        }
  
        if (length > end - start)
        {
          length = end - start;
          Array.Copy(buffer_, start, output, offset, length);
          start = 0;
          end = 0;
        }
        else
        {
          Array.Copy(buffer_, start, output, offset, length);
  
gt:         start += length;