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
00059 public class StreamManipulator
00060 {
00061 private byte[] window;
00062 private int window_start = 0;
00063 private int window_end = 0;
00064
00065 private uint buffer = 0;
00066 private int bits_in_buffer = 0;
00067
00076 public int PeekBits(int n)
00077 {
00078 if (bits_in_buffer < n) {
00079 if (window_start == window_end) {
00080 return -1;
00081 }
00082 buffer |= (uint)((window[window_start++] & 0xff |
00083 (window[window_start++] & 0xff) << 8) << bits_in_buffer);
00084 bits_in_buffer += 16;
00085 }
00086 return (int)(buffer & ((1 << n) - 1));
00087 }
00088
00094 public void DropBits(int n)
00095 {
00096 buffer >>= n;
00097 bits_in_buffer -= n;
00098 }
00099
00107 public int GetBits(int n)
00108 {
00109 int bits = PeekBits(n);
00110 if (bits >= 0) {
00111 DropBits(n);
00112 }
00113 return bits;
00114 }
00115
00123 public int AvailableBits {
00124 get {
00125 return bits_in_buffer;
00126 }
00127 }
00128
00135 public int AvailableBytes {
00136 get {
00137 return window_end - window_start + (bits_in_buffer >> 3);
00138 }
00139 }
00140
00144 public void SkipToByteBoundary()
00145 {
00146 buffer >>= (bits_in_buffer & 7);
00147 bits_in_buffer &= ~7;
00148 }
00149
00153 public bool IsNeedingInput {
00154 get {
00155 return window_start == window_end;
00156 }
00157 }
00158
00183 public int CopyBytes(byte[] output, int offset, int length)
00184 {
00185 if (length < 0) {
00186 throw new ArgumentOutOfRangeException("length");
00187 }
00188 if ((bits_in_buffer & 7) != 0) {
00189
00190 throw new InvalidOperationException("Bit buffer is not byte aligned!");
00191 }
00192
00193 int count = 0;
00194 while (bits_in_buffer > 0 && length > 0) {
00195 output[offset++] = (byte) buffer;
00196 buffer >>= 8;
00197 bits_in_buffer -= 8;
00198 length--;
00199 count++;
00200 }
00201
00202 if (length == 0) {
00203 return count;
00204 }
00205
00206 int avail = window_end - window_start;
00207 if (length > avail) {
00208 length = avail;
00209 }
00210 System.Array.Copy(window, window_start, output, offset, length);
00211 window_start += length;
00212
00213 if (((window_start - window_end) & 1) != 0) {
00214
00215 buffer = (uint)(window[window_start++] & 0xff);
00216 bits_in_buffer = 8;
00217 }
00218 return count + length;
00219 }
00220
00224 public StreamManipulator()
00225 {
00226 }
00227
00228
00232 public void Reset()
00233 {
00234 buffer = (uint)(window_start = window_end = bits_in_buffer = 0);
00235 }
00236
00244 public void SetInput(byte[] buf, int off, int len)
00245 {
00246 if (window_start < window_end) {
00247 throw new InvalidOperationException("Old input was not completely processed");
00248 }
00249
00250 int end = off + len;
00251
00252
00253
00254
00255 if (0 > off || off > end || end > buf.Length) {
00256 throw new ArgumentOutOfRangeException();
00257 }
00258
00259 if ((len & 1) != 0) {
00260
00261 buffer |= (uint)((buf[off++] & 0xff) << bits_in_buffer);
00262 bits_in_buffer += 8;
00263 }
00264
00265 window = buf;
00266 window_start = off;
00267 window_end = end;
00268 }
00269 }
00270 }