comparison Zip/Compression/Streams/OutputWindow.cs @ 1:94e25b786321

Re #311: can't read ZIP file packed by Linux app Archive Manager/File Roller Initial commit of clean SharpZipLib 0860 source. Only change is build paths.
author IBBoard <dev@ibboard.co.uk>
date Sat, 30 Oct 2010 14:03:17 +0000
parents
children
comparison
equal deleted inserted replaced
0:d16ef17fa7bb 1:94e25b786321
1 // OutputWindow.cs
2 //
3 // Copyright (C) 2001 Mike Krueger
4 //
5 // This file was translated from java, it was part of the GNU Classpath
6 // Copyright (C) 2001 Free Software Foundation, Inc.
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License
10 // as published by the Free Software Foundation; either version 2
11 // of the License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 //
22 // Linking this library statically or dynamically with other modules is
23 // making a combined work based on this library. Thus, the terms and
24 // conditions of the GNU General Public License cover the whole
25 // combination.
26 //
27 // As a special exception, the copyright holders of this library give you
28 // permission to link this library with independent modules to produce an
29 // executable, regardless of the license terms of these independent
30 // modules, and to copy and distribute the resulting executable under
31 // terms of your choice, provided that you also meet, for each linked
32 // independent module, the terms and conditions of the license of that
33 // module. An independent module is a module which is not derived from
34 // or based on this library. If you modify this library, you may extend
35 // this exception to your version of the library, but you are not
36 // obligated to do so. If you do not wish to do so, delete this
37 // exception statement from your version.
38
39 using System;
40
41
42 namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams
43 {
44
45 /// <summary>
46 /// Contains the output from the Inflation process.
47 /// We need to have a window so that we can refer backwards into the output stream
48 /// to repeat stuff.<br/>
49 /// Author of the original java version : John Leuner
50 /// </summary>
51 public class OutputWindow
52 {
53 #region Constants
54 const int WindowSize = 1 << 15;
55 const int WindowMask = WindowSize - 1;
56 #endregion
57
58 #region Instance Fields
59 byte[] window = new byte[WindowSize]; //The window is 2^15 bytes
60 int windowEnd;
61 int windowFilled;
62 #endregion
63
64 /// <summary>
65 /// Write a byte to this output window
66 /// </summary>
67 /// <param name="value">value to write</param>
68 /// <exception cref="InvalidOperationException">
69 /// if window is full
70 /// </exception>
71 public void Write(int value)
72 {
73 if (windowFilled++ == WindowSize) {
74 throw new InvalidOperationException("Window full");
75 }
76 window[windowEnd++] = (byte) value;
77 windowEnd &= WindowMask;
78 }
79
80
81 private void SlowRepeat(int repStart, int length, int distance)
82 {
83 while (length-- > 0) {
84 window[windowEnd++] = window[repStart++];
85 windowEnd &= WindowMask;
86 repStart &= WindowMask;
87 }
88 }
89
90 /// <summary>
91 /// Append a byte pattern already in the window itself
92 /// </summary>
93 /// <param name="length">length of pattern to copy</param>
94 /// <param name="distance">distance from end of window pattern occurs</param>
95 /// <exception cref="InvalidOperationException">
96 /// If the repeated data overflows the window
97 /// </exception>
98 public void Repeat(int length, int distance)
99 {
100 if ((windowFilled += length) > WindowSize) {
101 throw new InvalidOperationException("Window full");
102 }
103
104 int repStart = (windowEnd - distance) & WindowMask;
105 int border = WindowSize - length;
106 if ( (repStart <= border) && (windowEnd < border) ) {
107 if (length <= distance) {
108 System.Array.Copy(window, repStart, window, windowEnd, length);
109 windowEnd += length;
110 } else {
111 // We have to copy manually, since the repeat pattern overlaps.
112 while (length-- > 0) {
113 window[windowEnd++] = window[repStart++];
114 }
115 }
116 } else {
117 SlowRepeat(repStart, length, distance);
118 }
119 }
120
121 /// <summary>
122 /// Copy from input manipulator to internal window
123 /// </summary>
124 /// <param name="input">source of data</param>
125 /// <param name="length">length of data to copy</param>
126 /// <returns>the number of bytes copied</returns>
127 public int CopyStored(StreamManipulator input, int length)
128 {
129 length = Math.Min(Math.Min(length, WindowSize - windowFilled), input.AvailableBytes);
130 int copied;
131
132 int tailLen = WindowSize - windowEnd;
133 if (length > tailLen) {
134 copied = input.CopyBytes(window, windowEnd, tailLen);
135 if (copied == tailLen) {
136 copied += input.CopyBytes(window, 0, length - tailLen);
137 }
138 } else {
139 copied = input.CopyBytes(window, windowEnd, length);
140 }
141
142 windowEnd = (windowEnd + copied) & WindowMask;
143 windowFilled += copied;
144 return copied;
145 }
146
147 /// <summary>
148 /// Copy dictionary to window
149 /// </summary>
150 /// <param name="dictionary">source dictionary</param>
151 /// <param name="offset">offset of start in source dictionary</param>
152 /// <param name="length">length of dictionary</param>
153 /// <exception cref="InvalidOperationException">
154 /// If window isnt empty
155 /// </exception>
156 public void CopyDict(byte[] dictionary, int offset, int length)
157 {
158 if ( dictionary == null ) {
159 throw new ArgumentNullException("dictionary");
160 }
161
162 if (windowFilled > 0) {
163 throw new InvalidOperationException();
164 }
165
166 if (length > WindowSize) {
167 offset += length - WindowSize;
168 length = WindowSize;
169 }
170 System.Array.Copy(dictionary, offset, window, 0, length);
171 windowEnd = length & WindowMask;
172 }
173
174 /// <summary>
175 /// Get remaining unfilled space in window
176 /// </summary>
177 /// <returns>Number of bytes left in window</returns>
178 public int GetFreeSpace()
179 {
180 return WindowSize - windowFilled;
181 }
182
183 /// <summary>
184 /// Get bytes available for output in window
185 /// </summary>
186 /// <returns>Number of bytes filled</returns>
187 public int GetAvailable()
188 {
189 return windowFilled;
190 }
191
192 /// <summary>
193 /// Copy contents of window to output
194 /// </summary>
195 /// <param name="output">buffer to copy to</param>
196 /// <param name="offset">offset to start at</param>
197 /// <param name="len">number of bytes to count</param>
198 /// <returns>The number of bytes copied</returns>
199 /// <exception cref="InvalidOperationException">
200 /// If a window underflow occurs
201 /// </exception>
202 public int CopyOutput(byte[] output, int offset, int len)
203 {
204 int copyEnd = windowEnd;
205 if (len > windowFilled) {
206 len = windowFilled;
207 } else {
208 copyEnd = (windowEnd - windowFilled + len) & WindowMask;
209 }
210
211 int copied = len;
212 int tailLen = len - copyEnd;
213
214 if (tailLen > 0) {
215 System.Array.Copy(window, WindowSize - tailLen, output, offset, tailLen);
216 offset += tailLen;
217 len = copyEnd;
218 }
219 System.Array.Copy(window, copyEnd - len, output, offset, len);
220 windowFilled -= copied;
221 if (windowFilled < 0) {
222 throw new InvalidOperationException();
223 }
224 return copied;
225 }
226
227 /// <summary>
228 /// Reset by clearing window so <see cref="GetAvailable">GetAvailable</see> returns 0
229 /// </summary>
230 public void Reset()
231 {
232 windowFilled = windowEnd = 0;
233 }
234 }
235 }