//
package net.sf.zipme;
/**
* Contains the output from the Inflation process.
* We need to have a window so that we can refer backwards into the output stream
* to repeat stuff.
* @author John Leuner
* @since 1.1
*/
class OutputWindow {
private static final int WINDOW_SIZE=1 << 15;
private static final int WINDOW_MASK=WINDOW_SIZE - 1;
private byte[] window=new byte[WINDOW_SIZE];
private int window_end=0;
private int window_filled=0;
public void write( int abyte){
if (window_filled++ == WINDOW_SIZE) throw new IllegalStateException("Window full");
window[window_end++]=(byte)abyte;
window_end&=WINDOW_MASK;
}
private void slowRepeat( int rep_start, int len, int dist){
while (len-- > 0) {
window[window_end++]=window[rep_start++];
window_end&=WINDOW_MASK;
rep_start&=WINDOW_MASK;
}
}
public void repeat( int len, int dist){
if ((window_filled+=len) > WINDOW_SIZE) throw new IllegalStateException("Window full");
int rep_start=(window_end - dist) & WINDOW_MASK;
int border=WINDOW_SIZE - len;
if (rep_start <= border && window_end < border) {
if (len <= dist) {
System.arraycopy(window,rep_start,window,window_end,len);
window_end+=len;
}
else {
while (len-- > 0) window[window_end++]=window[rep_start++];
}
}
else slowRepeat(rep_start,len,dist);
}
public int copyStored( StreamManipulator input, int len){
len=Math.min(Math.min(len,WINDOW_SIZE - window_filled),input.getAvailableBytes());
int copied;
int tailLen=WINDOW_SIZE - window_end;
if (len > tailLen) {
copied=input.copyBytes(window,window_end,tailLen);
if (copied == tailLen) copied+=input.copyBytes(window,0,len - tailLen);
}
else copied=input.copyBytes(window,window_end,len);
window_end=(window_end + copied) & WINDOW_MASK;
window_filled+=copied;
return copied;
}
public void copyDict( byte[] dict, int offset, int len){
if (window_filled > 0) throw new IllegalStateException();
if (len > WINDOW_SIZE) {
offset+=len - WINDOW_SIZE;
len=WINDOW_SIZE;
}
System.arraycopy(dict,offset,window,0,len);
window_end=len & WINDOW_MASK;
}
public int getFreeSpace(){
return WINDOW_SIZE - window_filled;
}
public int getAvailable(){
return window_filled;
}
public int copyOutput( byte[] output, int offset, int len){
int copy_end=window_end;
if (len > window_filled) len=window_filled;
else copy_end=(window_end - window_filled + len) & WINDOW_MASK;
int copied=len;
int tailLen=len - copy_end;
if (tailLen > 0) {
System.arraycopy(window,WINDOW_SIZE - tailLen,output,offset,tailLen);
offset+=tailLen;
len=copy_end;
}
System.arraycopy(window,copy_end - len,output,offset,len);
window_filled-=copied;
if (window_filled < 0) throw new IllegalStateException();
return copied;
}
public void reset(){
window_filled=window_end=0;
}
}