// 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 PdfSharp.SharpZipLib.Zip.Compression { /// /// 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 /// internal class PendingBuffer { #region Instance Fields /// /// Internal work buffer /// byte[] buffer_; int start; int end; uint bits; int bitCount; #endregion #region Constructors /// /// construct instance using default buffer size of 4096 /// public PendingBuffer() : this(4096) { } /// /// construct instance using specified buffer size /// /// /// size to use for internal buffer /// public PendingBuffer(int bufferSize) { buffer_ = new byte[bufferSize]; } #endregion /// /// Clear internal state/buffers /// public void Reset() { start = end = bitCount = 0; } /// /// Write a byte to buffer /// /// /// The value to write /// 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); } /// /// Write a short value to buffer LSB first /// /// /// The value to write. /// 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)); } /// /// write an integer LSB first /// /// The value to write. 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)); } /// /// Write a block of data to buffer /// /// data to write /// offset of first byte to write /// number of bytes to write 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; } /// /// The number of bits written to the buffer /// public int BitCount { get { return bitCount; } } /// /// Align internal buffer on a byte boundary /// 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; } /// /// Write bits to internal buffer /// /// source of bits /// number of bits to write 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; } } /// /// Write a short value to internal buffer most significant byte first /// /// value to write 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); } /// /// Indicates if buffer has been flushed /// public bool IsFlushed { get { return end == 0; } } /// /// Flushes the pending buffer into the given output array. If the /// output array is to small, only a partial flush is done. /// /// The output array. /// The offset into output array. /// The maximum number of bytes to store. /// The number of bytes flushed. 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; } /// /// Convert internal buffer to byte array. /// Buffer is empty on completion /// /// /// The internal buffer contents converted to a byte array. /// public byte[] ToByteArray() { byte[] result = new byte[end - start]; System.Array.Copy(buffer_, start, result, 0, result.Length); start = 0; end = 0; return result; } } }