Statistics
| Branch: | Revision:

root / trunk / hammock / src / net35 / ICSharpCode.SharpZipLib.Silverlight / Zip / Compression / PendingBuffer.cs @ 0eea575a

History | View | Annotate | Download (8 kB)

1
// PendingBuffer.cs
2
//
3
// Copyright (C) 2001 Mike Krueger
4
// Copyright (C) 2004 John Reilly
5
//
6
// This file was translated from java, it was part of the GNU Classpath
7
// Copyright (C) 2001 Free Software Foundation, Inc.
8
//
9
// This program is free software; you can redistribute it and/or
10
// modify it under the terms of the GNU General Public License
11
// as published by the Free Software Foundation; either version 2
12
// of the License, or (at your option) any later version.
13
//
14
// This program is distributed in the hope that it will be useful,
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
// GNU General Public License for more details.
18
//
19
// You should have received a copy of the GNU General Public License
20
// along with this program; if not, write to the Free Software
21
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
//
23
// Linking this library statically or dynamically with other modules is
24
// making a combined work based on this library.  Thus, the terms and
25
// conditions of the GNU General Public License cover the whole
26
// combination.
27
// 
28
// As a special exception, the copyright holders of this library give you
29
// permission to link this library with independent modules to produce an
30
// executable, regardless of the license terms of these independent
31
// modules, and to copy and distribute the resulting executable under
32
// terms of your choice, provided that you also meet, for each linked
33
// independent module, the terms and conditions of the license of that
34
// module.  An independent module is a module which is not derived from
35
// or based on this library.  If you modify this library, you may extend
36
// this exception to your version of the library, but you are not
37
// obligated to do so.  If you do not wish to do so, delete this
38
// exception statement from your version.
39

    
40
namespace ICSharpCode.SharpZipLib.Silverlight.Zip.Compression
41
{
42
    /// <summary>
43
    /// This class is general purpose class for writing data to a buffer.
44
    /// 
45
    /// It allows you to write bits as well as bytes
46
    /// Based on DeflaterPending.java
47
    /// 
48
    /// author of the original java version : Jochen Hoenicke
49
    /// </summary>
50
    public class PendingBuffer
51
    {
52
        #region Instance Fields
53
        /// <summary>
54
        /// Internal work buffer
55
        /// </summary>
56
        readonly byte[] buffer_;
57
		
58
        int    start;
59
        int    end;
60
		
61
        uint   bits;
62
        int    bitCount;
63
        #endregion
64

    
65
        #region Constructors
66
        /// <summary>
67
        /// construct instance using default buffer size of 4096
68
        /// </summary>
69
        public PendingBuffer() : this( 4096 )
70
        {
71
        }
72
		
73
        /// <summary>
74
        /// construct instance using specified buffer size
75
        /// </summary>
76
        /// <param name="bufferSize">
77
        /// size to use for internal buffer
78
        /// </param>
79
        public PendingBuffer(int bufferSize)
80
        {
81
            buffer_ = new byte[bufferSize];
82
        }
83

    
84
        #endregion
85

    
86
        /// <summary>
87
        /// Clear internal state/buffers
88
        /// </summary>
89
        public void Reset() 
90
        {
91
            start = end = bitCount = 0;
92
        }
93

    
94
        /// <summary>
95
        /// Write a byte to buffer
96
        /// </summary>
97
        /// <param name="value">
98
        /// The value to write
99
        /// </param>
100
        public void WriteByte(int value)
101
        {
102
            buffer_[end++] = unchecked((byte) value);
103
        }
104

    
105
        /// <summary>
106
        /// Write a short value to buffer LSB first
107
        /// </summary>
108
        /// <param name="value">
109
        /// The value to write.
110
        /// </param>
111
        public void WriteShort(int value)
112
        {
113
            buffer_[end++] = unchecked((byte) value);
114
            buffer_[end++] = unchecked((byte) (value >> 8));
115
        }
116

    
117
        /// <summary>
118
        /// write an integer LSB first
119
        /// </summary>
120
        /// <param name="value">The value to write.</param>
121
        public void WriteInt(int value)
122
        {
123
            buffer_[end++] = unchecked((byte) value);
124
            buffer_[end++] = unchecked((byte) (value >> 8));
125
            buffer_[end++] = unchecked((byte) (value >> 16));
126
            buffer_[end++] = unchecked((byte) (value >> 24));
127
        }
128
		
129
        /// <summary>
130
        /// Write a block of data to buffer
131
        /// </summary>
132
        /// <param name="block">data to write</param>
133
        /// <param name="offset">offset of first byte to write</param>
134
        /// <param name="length">number of bytes to write</param>
135
        public void WriteBlock(byte[] block, int offset, int length)
136
        {
137
            System.Array.Copy(block, offset, buffer_, end, length);
138
            end += length;
139
        }
140

    
141
        /// <summary>
142
        /// The number of bits written to the buffer
143
        /// </summary>
144
        public int BitCount {
145
            get {
146
                return bitCount;
147
            }
148
        }
149
		
150
        /// <summary>
151
        /// Align internal buffer on a byte boundary
152
        /// </summary>
153
        public void AlignToByte() 
154
        {
155
            if (bitCount > 0) 
156
            {
157
                buffer_[end++] = unchecked((byte) bits);
158
                if (bitCount > 8) {
159
                    buffer_[end++] = unchecked((byte) (bits >> 8));
160
                }
161
            }
162
            bits = 0;
163
            bitCount = 0;
164
        }
165

    
166
        /// <summary>
167
        /// Write bits to internal buffer
168
        /// </summary>
169
        /// <param name="b">source of bits</param>
170
        /// <param name="count">number of bits to write</param>
171
        public void WriteBits(int b, int count)
172
        {
173
            bits |= (uint)(b << bitCount);
174
            bitCount += count;
175
            if (bitCount < 16)
176
            {
177
                return;
178
            }
179
            buffer_[end++] = unchecked((byte) bits);
180
            buffer_[end++] = unchecked((byte) (bits >> 8));
181
            bits >>= 16;
182
            bitCount -= 16;
183
        }
184

    
185
        /// <summary>
186
        /// Write a short value to internal buffer most significant byte first
187
        /// </summary>
188
        /// <param name="s">value to write</param>
189
        public void WriteShortMSB(int s) 
190
        {
191
            buffer_[end++] = unchecked((byte) (s >> 8));
192
            buffer_[end++] = unchecked((byte) s);
193
        }
194
		
195
        /// <summary>
196
        /// Indicates if buffer has been flushed
197
        /// </summary>
198
        public bool IsFlushed {
199
            get {
200
                return end == 0;
201
            }
202
        }
203
		
204
        /// <summary>
205
        /// Flushes the pending buffer into the given output array.  If the
206
        /// output array is to small, only a partial flush is done.
207
        /// </summary>
208
        /// <param name="output">The output array.</param>
209
        /// <param name="offset">The offset into output array.</param>
210
        /// <param name="length">The maximum number of bytes to store.</param>
211
        /// <returns>The number of bytes flushed.</returns>
212
        public int Flush(byte[] output, int offset, int length) 
213
        {
214
            if (bitCount >= 8) {
215
                buffer_[end++] = unchecked((byte) bits);
216
                bits >>= 8;
217
                bitCount -= 8;
218
            }
219

    
220
            if (length > end - start) {
221
                length = end - start;
222
                System.Array.Copy(buffer_, start, output, offset, length);
223
                start = 0;
224
                end = 0;
225
            } else {
226
                System.Array.Copy(buffer_, start, output, offset, length);
227
                start += length;
228
            }
229
            return length;
230
        }
231

    
232
        /// <summary>
233
        /// Convert internal buffer to byte array.
234
        /// Buffer is empty on completion
235
        /// </summary>
236
        /// <returns>
237
        /// The internal buffer contents converted to a byte array.
238
        /// </returns>
239
        public byte[] ToByteArray()
240
        {
241
            var result = new byte[end - start];
242
            System.Array.Copy(buffer_, start, result, 0, result.Length);
243
            start = 0;
244
            end = 0;
245
            return result;
246
        }
247
    }
248
}