Upload 2.0.2
[physicsfs] / lzma / CS / 7zip / Compress / LZ / LzOutWindow.cs
1 // LzOutWindow.cs
2
3 namespace SevenZip.Compression.LZ
4 {
5         public class OutWindow
6         {
7                 byte[] _buffer = null;
8                 uint _pos;
9                 uint _windowSize = 0;
10                 uint _streamPos;
11                 System.IO.Stream _stream;
12
13                 public uint TrainSize = 0;
14
15                 public void Create(uint windowSize)
16                 {
17                         if (_windowSize != windowSize)
18                         {
19                                 // System.GC.Collect();
20                                 _buffer = new byte[windowSize];
21                         }
22                         _windowSize = windowSize;
23                         _pos = 0;
24                         _streamPos = 0;
25                 }
26
27                 public void Init(System.IO.Stream stream, bool solid)
28                 {
29                         ReleaseStream();
30                         _stream = stream;
31                         if (!solid)
32                         {
33                                 _streamPos = 0;
34                                 _pos = 0;
35                                 TrainSize = 0;
36                         }
37                 }
38         
39                 public bool Train(System.IO.Stream stream)
40                 {
41                         long len = stream.Length;
42                         uint size = (len < _windowSize) ? (uint)len : _windowSize;
43                         TrainSize = size;
44                         stream.Position = len - size;
45                         _streamPos = _pos = 0;
46                         while (size > 0)
47                         {
48                                 uint curSize = _windowSize - _pos;
49                                 if (size < curSize)
50                                         curSize = size;
51                                 int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize);
52                                 if (numReadBytes == 0)
53                                         return false;
54                                 size -= (uint)numReadBytes;
55                                 _pos += (uint)numReadBytes;
56                                 _streamPos += (uint)numReadBytes;
57                                 if (_pos == _windowSize)
58                                         _streamPos = _pos = 0;
59                         }
60                         return true;
61                 }
62
63                 public void ReleaseStream()
64                 {
65                         Flush();
66                         _stream = null;
67                 }
68
69                 public void Flush()
70                 {
71                         uint size = _pos - _streamPos;
72                         if (size == 0)
73                                 return;
74                         _stream.Write(_buffer, (int)_streamPos, (int)size);
75                         if (_pos >= _windowSize)
76                                 _pos = 0;
77                         _streamPos = _pos;
78                 }
79
80                 public void CopyBlock(uint distance, uint len)
81                 {
82                         uint pos = _pos - distance - 1;
83                         if (pos >= _windowSize)
84                                 pos += _windowSize;
85                         for (; len > 0; len--)
86                         {
87                                 if (pos >= _windowSize)
88                                         pos = 0;
89                                 _buffer[_pos++] = _buffer[pos++];
90                                 if (_pos >= _windowSize)
91                                         Flush();
92                         }
93                 }
94
95                 public void PutByte(byte b)
96                 {
97                         _buffer[_pos++] = b;
98                         if (_pos >= _windowSize)
99                                 Flush();
100                 }
101
102                 public byte GetByte(uint distance)
103                 {
104                         uint pos = _pos - distance - 1;
105                         if (pos >= _windowSize)
106                                 pos += _windowSize;
107                         return _buffer[pos];
108                 }
109         }
110 }