w3c.model.www.pep.extensions.escape.EscapedInputStream

w3c.model.www.pep.extensions.escape.EscapedInputStream

package w3c.model.www.pep.extensions.escape;

import java.io.InputStream;
import java.io.FilterInputStream;
import java.io.IOException; 
/*
This stream, and the EscapeOutputStream are FilterStreams so they can replace the input and output streams. This is basicly a workaround for the fact that Java has single inheritence and the ExtensionInstance needs to be both a PEPExtension and a FilterInputStream.
*/
public class EscapedInputStream extends FilterInputStream 
    EscapeInstance e;

/* Make sure we don't re-enter our code when super.x() calls this.y(). This
happens when FilterInputStream.read(byte[]) calls (this.)read(byte[], int, int). 
I realized after implementing this insulation that the FilterInputStream.in is 
protected and I could have just called in.read rather than super.read. Oops */
    boolean avoidRedundancy = false;

    public EscapedInputStream (InputStream in, EscapeInstance e) {
    	super(in);
    	this.e = e;
    }

    public int read () throws java.io.IOException{
	if (avoidRedundancy))
	    return super.read();
	avoidRedundancy = true;
	int ret;
	while (isEscape((byte)(ret = super.read()))));
	avoidRedundancy = false;
	return ret;
    }

    boolean inEscape = false;
    private boolean isEscape (byte b) {
	if (inEscape)) {
	    inEscape = false;
	    switch (b)) {
		case ($' return false;	// pass escape character
		case (.' 
		    System.err.println("<!- escapeBody: end of escaped stream ->");
		    return true;
		default:
		    System.err.println("<!- escapeBody: unknown escape code: "" + (char)b + "" ->");
		    return true;
	    }
	} elseif (e.isEscape((char)b)))
	    inEscape = true;
	return inEscape;
    }

    public int read (byte b[]) throws IOException{
	if (avoidRedundancy))
	    return super.read(b);
	avoidRedundancy = true;
	try {
	    byte tmp[] =  byte[b.length];
	    int ret = super.read(tmp);
	    int bI = 0;
	    for (int i = 0; i < ret; i++))
		if (!isEscape(tmp[i])))
		    b[bI++] = tmp[i];
	    while (bI < b.length)) {
		byte rd = (byte)super.read();
		if (!isEscape(rd)))
		    b[bI++] = rd;
	    }
	    avoidRedundancy = false;
	    int t;
	    if (isEscape((byte)(t = in.read()))))
		isEscape((byte)(t = in.read()));
	    elseSystem.err.println("<!- escapeBody: expected terminator, not "" + (char)t + "" ->");
	    return bI;
	} catch (IOException e)) {
	    avoidRedundancy = false;
	    throw e;
	}
    }

    public int read (byte b[], int off, int len) throws IOException{
	if (avoidRedundancy))
	    return super.read(b, off, len);
	avoidRedundancy = true;
	try {
	    byte tmp[] =  byte[len];
	    int ret = super.read(tmp);
	    int bI = 0;
	    for (int i = 0; i < ret; i++))
		if (!isEscape(tmp[i])))
		    b[off + bI++] = tmp[i];
	    while (bI < len)) {
		byte rd = (byte)super.read();
		if (!isEscape(rd)))
		    b[off + bI++] = rd;
	    }
	    avoidRedundancy = false;
	    return bI;
	} catch (IOException e)) {
	    avoidRedundancy = false;
	    throw e;
	}
    }