View Javadoc

1   // OutputWindow.java, created Mon Jul  8  4:06:18 2002 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.ClassLib.Common.java.util.zip;
5   
6   /***
7    * OutputWindow
8    *
9    * @author  John Whaley <jwhaley@alum.mit.edu>
10   * @version $Id: OutputWindow.java 1451 2004-03-09 06:27:08Z jwhaley $
11   */
12  class OutputWindow {
13    private final int WINDOW_SIZE = 1 << 15;
14    private final int WINDOW_MASK = WINDOW_SIZE - 1;
15  
16    private byte[] window = new byte[WINDOW_SIZE]; //The window is 2^15 bytes
17    private int window_end  = 0;
18    private int window_filled = 0;
19  
20    public void write(int abyte)
21    {
22      if (window_filled++ == WINDOW_SIZE)
23        throw new java.lang.IllegalStateException("Window full");
24      window[window_end++] = (byte) abyte;
25      window_end &= WINDOW_MASK;
26    }
27  
28  
29    private final void slowRepeat(int rep_start, int len, int dist)
30    {
31      while (len-- > 0)
32        {
33          window[window_end++] = window[rep_start++];
34          window_end &= WINDOW_MASK;
35          rep_start &= WINDOW_MASK;
36        }
37    }
38  
39    public void repeat(int len, int dist)
40    {
41      if ((window_filled += len) > WINDOW_SIZE)
42        throw new java.lang.IllegalStateException("Window full");
43  
44      int rep_start = (window_end - dist) & WINDOW_MASK;
45      int border = WINDOW_SIZE - len;
46      if (rep_start <= border && window_end < border)
47        {
48          if (len <= dist)
49            {
50              java.lang.System.arraycopy(window, rep_start, window, window_end, len);
51              window_end += len;
52            }
53          else
54            {
55              /* We have to copy manually, since the repeat pattern overlaps.
56               */
57              while (len-- > 0)
58                window[window_end++] = window[rep_start++];
59            }
60        }
61      else
62        slowRepeat(rep_start, len, dist);
63    }
64  
65    public int copyStored(StreamManipulator input, int len)
66    {
67      len = java.lang.Math.min(java.lang.Math.min(len, WINDOW_SIZE - window_filled), 
68                     input.getAvailableBytes());
69      int copied;
70  
71      int tailLen = WINDOW_SIZE - window_end;
72      if (len > tailLen)
73        {
74          copied = input.copyBytes(window, window_end, tailLen);
75          if (copied == tailLen)
76            copied += input.copyBytes(window, 0, len - tailLen);
77        }
78      else
79        copied = input.copyBytes(window, window_end, len);
80  
81      window_end = (window_end + copied) & WINDOW_MASK;
82      window_filled += copied;
83      return copied;
84    }
85  
86    public void copyDict(byte[] dict, int offset, int len)
87    {
88      if (window_filled > 0)
89        throw new java.lang.IllegalStateException();
90  
91      if (len > WINDOW_SIZE)
92        {
93          offset += len - WINDOW_SIZE;
94          len = WINDOW_SIZE;
95        }
96      java.lang.System.arraycopy(dict, offset, window, 0, len);
97      window_end = len & WINDOW_MASK;
98    }
99  
100   public int getFreeSpace()
101   {
102     return WINDOW_SIZE - window_filled;
103   }
104 
105   public int getAvailable()
106   {
107     return window_filled;
108   }
109 
110   public int copyOutput(byte[] output, int offset, int len)
111   {
112     int copy_end = window_end;
113     if (len > window_filled)
114       len = window_filled;
115     else
116       copy_end = (window_end - window_filled + len) & WINDOW_MASK;
117 
118     int copied = len;
119     int tailLen = len - copy_end;
120 
121     if (tailLen > 0)
122       {
123         java.lang.System.arraycopy(window, WINDOW_SIZE - tailLen,
124                          output, offset, tailLen);
125         offset += tailLen;
126         len = copy_end;
127       }
128     java.lang.System.arraycopy(window, copy_end - len, output, offset, len);
129     window_filled -= copied;
130     if (window_filled < 0)
131       throw new java.lang.IllegalStateException();
132     return copied;
133   }
134 
135   public void reset() {
136     window_filled = window_end = 0;
137   }
138 }