// 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 ICSharpCode.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> 
 | 
    public class PendingBuffer 
 | 
    { 
 | 
        #region Instance Fields 
 | 
        /// <summary> 
 | 
        /// Internal work buffer 
 | 
        /// </summary> 
 | 
        byte[] buffer_; 
 | 
         
 | 
        int    start; 
 | 
        int    end; 
 | 
         
 | 
        uint   bits; 
 | 
        int    bitCount; 
 | 
        #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 byte to buffer 
 | 
        /// </summary> 
 | 
        /// <param name="value"> 
 | 
        /// The value to write 
 | 
        /// </param> 
 | 
        public void WriteByte(int value) 
 | 
        { 
 | 
#if DebugDeflation 
 | 
            if (DeflaterConstants.DEBUGGING && (start != 0) ) 
 | 
            { 
 | 
                throw new SharpZipBaseException("Debug check: start != 0"); 
 | 
            } 
 | 
#endif 
 | 
            buffer_[end++] = unchecked((byte) value); 
 | 
        } 
 | 
  
 | 
        /// <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 an integer LSB first 
 | 
        /// </summary> 
 | 
        /// <param name="value">The value to write.</param> 
 | 
        public void WriteInt(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)); 
 | 
            buffer_[end++] = unchecked((byte) (value >> 16)); 
 | 
            buffer_[end++] = unchecked((byte) (value >> 24)); 
 | 
        } 
 | 
         
 | 
        /// <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 
 | 
            System.Array.Copy(block, offset, buffer_, end, length); 
 | 
            end += length; 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// The number of bits written to the buffer 
 | 
        /// </summary> 
 | 
        public int BitCount { 
 | 
            get { 
 | 
                return bitCount; 
 | 
            } 
 | 
        } 
 | 
         
 | 
        /// <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; 
 | 
                System.Array.Copy(buffer_, start, output, offset, length); 
 | 
                start = 0; 
 | 
                end = 0; 
 | 
            } else { 
 | 
                System.Array.Copy(buffer_, start, output, offset, length); 
 | 
                start += length; 
 | 
            } 
 | 
            return length; 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// Convert internal buffer to byte array. 
 | 
        /// Buffer is empty on completion 
 | 
        /// </summary> 
 | 
        /// <returns> 
 | 
        /// The internal buffer contents converted to a byte array. 
 | 
        /// </returns> 
 | 
        public byte[] ToByteArray() 
 | 
        { 
 | 
            byte[] result = new byte[end - start]; 
 | 
            System.Array.Copy(buffer_, start, result, 0, result.Length); 
 | 
            start = 0; 
 | 
            end = 0; 
 | 
            return result; 
 | 
        } 
 | 
    } 
 | 
}     
 |