**** Merged from MCS ****
[mono-project.git] / mcs / class / ICSharpCode.SharpZipLib / ICSharpCode.SharpZipLib / Zip / Compression / Streams / OutputWindow.cs
blob426c1f752d31cc53d3cff29b3ce60a5f82b8b600
1 // OutputWindow.cs
2 // Copyright (C) 2001 Mike Krueger
3 //
4 // This file was translated from java, it was part of the GNU Classpath
5 // Copyright (C) 2001 Free Software Foundation, Inc.
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 // Linking this library statically or dynamically with other modules is
22 // making a combined work based on this library. Thus, the terms and
23 // conditions of the GNU General Public License cover the whole
24 // combination.
25 //
26 // As a special exception, the copyright holders of this library give you
27 // permission to link this library with independent modules to produce an
28 // executable, regardless of the license terms of these independent
29 // modules, and to copy and distribute the resulting executable under
30 // terms of your choice, provided that you also meet, for each linked
31 // independent module, the terms and conditions of the license of that
32 // module. An independent module is a module which is not derived from
33 // or based on this library. If you modify this library, you may extend
34 // this exception to your version of the library, but you are not
35 // obligated to do so. If you do not wish to do so, delete this
36 // exception statement from your version.
38 using System;
40 namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams
43 /// <summary>
44 /// Contains the output from the Inflation process.
45 /// We need to have a window so that we can refer backwards into the output stream
46 /// to repeat stuff.
47 ///
48 /// author of the original java version : John Leuner
49 /// </summary>
50 public class OutputWindow
52 private static int WINDOW_SIZE = 1 << 15;
53 private static int WINDOW_MASK = WINDOW_SIZE - 1;
55 private byte[] window = new byte[WINDOW_SIZE]; //The window is 2^15 bytes
56 private int windowEnd = 0;
57 private int windowFilled = 0;
59 public void Write(int abyte)
61 if (windowFilled++ == WINDOW_SIZE) {
62 throw new InvalidOperationException("Window full");
64 window[windowEnd++] = (byte) abyte;
65 windowEnd &= WINDOW_MASK;
69 private void SlowRepeat(int repStart, int len, int dist)
71 while (len-- > 0) {
72 window[windowEnd++] = window[repStart++];
73 windowEnd &= WINDOW_MASK;
74 repStart &= WINDOW_MASK;
78 public void Repeat(int len, int dist)
80 if ((windowFilled += len) > WINDOW_SIZE) {
81 throw new InvalidOperationException("Window full");
84 int rep_start = (windowEnd - dist) & WINDOW_MASK;
85 int border = WINDOW_SIZE - len;
86 if (rep_start <= border && windowEnd < border) {
87 if (len <= dist) {
88 System.Array.Copy(window, rep_start, window, windowEnd, len);
89 windowEnd += len;
90 } else {
91 /* We have to copy manually, since the repeat pattern overlaps.
93 while (len-- > 0) {
94 window[windowEnd++] = window[rep_start++];
97 } else {
98 SlowRepeat(rep_start, len, dist);
102 public int CopyStored(StreamManipulator input, int len)
104 len = Math.Min(Math.Min(len, WINDOW_SIZE - windowFilled), input.AvailableBytes);
105 int copied;
107 int tailLen = WINDOW_SIZE - windowEnd;
108 if (len > tailLen) {
109 copied = input.CopyBytes(window, windowEnd, tailLen);
110 if (copied == tailLen) {
111 copied += input.CopyBytes(window, 0, len - tailLen);
113 } else {
114 copied = input.CopyBytes(window, windowEnd, len);
117 windowEnd = (windowEnd + copied) & WINDOW_MASK;
118 windowFilled += copied;
119 return copied;
122 public void CopyDict(byte[] dict, int offset, int len)
124 if (windowFilled > 0) {
125 throw new InvalidOperationException();
128 if (len > WINDOW_SIZE) {
129 offset += len - WINDOW_SIZE;
130 len = WINDOW_SIZE;
132 System.Array.Copy(dict, offset, window, 0, len);
133 windowEnd = len & WINDOW_MASK;
136 public int GetFreeSpace()
138 return WINDOW_SIZE - windowFilled;
141 public int GetAvailable()
143 return windowFilled;
146 public int CopyOutput(byte[] output, int offset, int len)
148 int copy_end = windowEnd;
149 if (len > windowFilled) {
150 len = windowFilled;
151 } else {
152 copy_end = (windowEnd - windowFilled + len) & WINDOW_MASK;
155 int copied = len;
156 int tailLen = len - copy_end;
158 if (tailLen > 0) {
159 System.Array.Copy(window, WINDOW_SIZE - tailLen, output, offset, tailLen);
160 offset += tailLen;
161 len = copy_end;
163 System.Array.Copy(window, copy_end - len, output, offset, len);
164 windowFilled -= copied;
165 if (windowFilled < 0) {
166 throw new InvalidOperationException();
168 return copied;
171 public void Reset()
173 windowFilled = windowEnd = 0;