00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 using System;
00040
00041 namespace ICSharpCode.SharpZipLib.Zip.Compression.Streams
00042 {
00043
00050 public class OutputWindow
00051 {
00052 private static int WINDOW_SIZE = 1 << 15;
00053 private static int WINDOW_MASK = WINDOW_SIZE - 1;
00054
00055 private byte[] window = new byte[WINDOW_SIZE];
00056 private int windowEnd = 0;
00057 private int windowFilled = 0;
00058
00066 public void Write(int abyte)
00067 {
00068 if (windowFilled++ == WINDOW_SIZE) {
00069 throw new InvalidOperationException("Window full");
00070 }
00071 window[windowEnd++] = (byte) abyte;
00072 windowEnd &= WINDOW_MASK;
00073 }
00074
00075
00076 private void SlowRepeat(int repStart, int len, int dist)
00077 {
00078 while (len-- > 0) {
00079 window[windowEnd++] = window[repStart++];
00080 windowEnd &= WINDOW_MASK;
00081 repStart &= WINDOW_MASK;
00082 }
00083 }
00084
00093 public void Repeat(int len, int dist)
00094 {
00095 if ((windowFilled += len) > WINDOW_SIZE) {
00096 throw new InvalidOperationException("Window full");
00097 }
00098
00099 int rep_start = (windowEnd - dist) & WINDOW_MASK;
00100 int border = WINDOW_SIZE - len;
00101 if (rep_start <= border && windowEnd < border) {
00102 if (len <= dist) {
00103 System.Array.Copy(window, rep_start, window, windowEnd, len);
00104 windowEnd += len;
00105 } else {
00106
00107 while (len-- > 0) {
00108 window[windowEnd++] = window[rep_start++];
00109 }
00110 }
00111 } else {
00112 SlowRepeat(rep_start, len, dist);
00113 }
00114 }
00115
00122 public int CopyStored(StreamManipulator input, int len)
00123 {
00124 len = Math.Min(Math.Min(len, WINDOW_SIZE - windowFilled), input.AvailableBytes);
00125 int copied;
00126
00127 int tailLen = WINDOW_SIZE - windowEnd;
00128 if (len > tailLen) {
00129 copied = input.CopyBytes(window, windowEnd, tailLen);
00130 if (copied == tailLen) {
00131 copied += input.CopyBytes(window, 0, len - tailLen);
00132 }
00133 } else {
00134 copied = input.CopyBytes(window, windowEnd, len);
00135 }
00136
00137 windowEnd = (windowEnd + copied) & WINDOW_MASK;
00138 windowFilled += copied;
00139 return copied;
00140 }
00141
00151 public void CopyDict(byte[] dict, int offset, int len)
00152 {
00153 if (windowFilled > 0) {
00154 throw new InvalidOperationException();
00155 }
00156
00157 if (len > WINDOW_SIZE) {
00158 offset += len - WINDOW_SIZE;
00159 len = WINDOW_SIZE;
00160 }
00161 System.Array.Copy(dict, offset, window, 0, len);
00162 windowEnd = len & WINDOW_MASK;
00163 }
00164
00169 public int GetFreeSpace()
00170 {
00171 return WINDOW_SIZE - windowFilled;
00172 }
00173
00178 public int GetAvailable()
00179 {
00180 return windowFilled;
00181 }
00182
00193 public int CopyOutput(byte[] output, int offset, int len)
00194 {
00195 int copy_end = windowEnd;
00196 if (len > windowFilled) {
00197 len = windowFilled;
00198 } else {
00199 copy_end = (windowEnd - windowFilled + len) & WINDOW_MASK;
00200 }
00201
00202 int copied = len;
00203 int tailLen = len - copy_end;
00204
00205 if (tailLen > 0) {
00206 System.Array.Copy(window, WINDOW_SIZE - tailLen, output, offset, tailLen);
00207 offset += tailLen;
00208 len = copy_end;
00209 }
00210 System.Array.Copy(window, copy_end - len, output, offset, len);
00211 windowFilled -= copied;
00212 if (windowFilled < 0) {
00213 throw new InvalidOperationException();
00214 }
00215 return copied;
00216 }
00217
00221 public void Reset()
00222 {
00223 windowFilled = windowEnd = 0;
00224 }
00225 }
00226 }