package uci.graphedit; /** * An implementation of interface CharStream, where the stream is assumed to * contain only ASCII characters (with java-like unicode escape processing). */ public final class ASCII_UCodeESC_CharStream { static final boolean hexchar(char c) { if (c < '0' || c > 'f') return false; if (c <= '9') return true; if (c >= 'a' && c <= 'f') return true; if (c >= 'A') return true; return false; } static final int hexval(char c) { if (c >= '0' && c <= '9') return (int)c - (int)'0'; if (c >= 'a' && c <= 'f') return (int)c - (int)'a' + 10; return (int)c - (int)'A' + 10; } public int bufpos = -1; int bufsize; int available; int tokenBegin; private int bufline[]; private int bufcolumn[]; private int column = 0; private int line = 1; private java.io.InputStream inputStream; private boolean prevCharIsCR = false; private boolean prevCharIsLF = false; private byte[] nextCharBuf; private char[] buffer; private int maxNextCharInd = 0; private int nextCharInd = -1; private final void ExpandBuff(boolean wrapAround) { char[] newbuffer = new char[bufsize + 2048]; int newbufline[] = new int[bufsize + 2048]; int newbufcolumn[] = new int[bufsize + 2048]; try { if (wrapAround) { System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); System.arraycopy(buffer, tokenBegin, newbuffer, bufsize - tokenBegin, bufpos); buffer.finalize(); buffer = newbuffer; System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); bufline.finalize(); bufline = newbufline; System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); bufcolumn.finalize(); bufcolumn = newbufcolumn; bufpos += (bufsize - tokenBegin); } else { System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); buffer.finalize(); buffer = newbuffer; System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); bufline.finalize(); bufline = newbufline; System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); bufcolumn.finalize(); bufcolumn = newbufcolumn; bufpos -= tokenBegin; } } catch (Throwable t) { System.out.println("Error : " + t.getClass().getName()); throw new Error(); } available = (bufsize += 2048); tokenBegin = 0; } private final void FillBuff() throws java.io.IOException { int i; if (maxNextCharInd == 4096) maxNextCharInd = nextCharInd = 0; if ((i = inputStream.read(nextCharBuf, maxNextCharInd, 4096 - maxNextCharInd)) == -1) { bufpos--; throw new java.io.IOException(); } else maxNextCharInd += i; } private final char ReadByte() throws java.io.IOException { if (++nextCharInd >= maxNextCharInd) FillBuff(); return (char)nextCharBuf[nextCharInd]; } public final char BeginToken() throws java.io.IOException { if (inBuf > 0) { --inBuf; return buffer[tokenBegin = (bufpos == bufsize - 1) ? (bufpos = 0) : ++bufpos]; } tokenBegin = 0; bufpos = -1; return readChar(); } private final void AdjustBuffSize() { if (available == bufsize) { if (tokenBegin > 2048) { bufpos = 0; available = tokenBegin; } else ExpandBuff(false); } else if (available >= tokenBegin) available = bufsize; else if ((tokenBegin - available) < 2048) ExpandBuff(true); else available = tokenBegin; } private final void UpdateLineColumn(char c) { column++; if (prevCharIsLF) { prevCharIsLF = false; line += (column = 1); } else if (prevCharIsCR) { prevCharIsCR = false; if (c == '\n') { prevCharIsLF = true; } else line += (column = 1); } switch (c) { case '\r' : prevCharIsCR = true; break; case '\n' : prevCharIsLF = true; break; case '\t' : column += (9 - (column & 07)); break; default : break; } bufline[bufpos] = line; bufcolumn[bufpos] = column; } private int inBuf = 0; public final char readChar() throws java.io.IOException { if (inBuf > 0) { --inBuf; return buffer[(bufpos == bufsize - 1) ? (bufpos = 0) : ++bufpos]; } char c; if (++bufpos == available) AdjustBuffSize(); if (((buffer[bufpos] = c = (char)ReadByte()) == '\\')) { UpdateLineColumn(c); int backSlashCnt = 1; for (;;) // Read all the backslashes { if (++bufpos == available) AdjustBuffSize(); if ((buffer[bufpos] = c = (char)ReadByte()) != '\\') { UpdateLineColumn(c); // found a non-backslash char. if ((c == 'u') && ((backSlashCnt & 1) == 1)) { if (--bufpos < 0) bufpos = bufsize - 1; break; } backup(backSlashCnt); return '\\'; } UpdateLineColumn(c); backSlashCnt++; } // Here, we have seen an odd number of backslash's followed by a 'u' ++column; while ((c = (char)ReadByte()) == 'u') ++column; int ucode = 0; if (!hexchar(c)) { System.err.println("Invalid escape character at line " + line + " column " + column + "."); throw new Error(); } ucode = ucode*16 + hexval(c); if (!hexchar((c = (char)ReadByte()))) { System.err.println("Invalid escape character at line " + line + " column " + (column + 1) + "."); throw new Error(); } ucode = ucode*16 + hexval(c); if (!hexchar((c = (char)ReadByte()))) { System.err.println("Invalid escape character at line " + line + " column " + (column + 2) + "."); throw new Error(); } ucode = ucode*16 + hexval(c); if (!hexchar((c = (char)ReadByte()))) { System.err.println("Invalid escape character at line " + line + " column " + (column + 3) + "."); throw new Error(); } bufline[bufpos] = line; bufcolumn[bufpos] = (column += 4); buffer[bufpos] = c = (char)(ucode*16 + hexval(c)); if (backSlashCnt == 1) return c; else { backup(backSlashCnt - 1); return '\\'; } } else { UpdateLineColumn(c); return (c); } } public final int getColumn() { return bufcolumn[bufpos]; } public final int getLine() { return bufline[bufpos]; } public final void backup(int amount) { inBuf += amount; if ((bufpos -= amount) < 0) bufpos += bufsize; } public ASCII_UCodeESC_CharStream(java.io.InputStream dstream, int startline, int startcolumn, int buffersize) { inputStream = dstream; line = startline; column = startcolumn - 1; available = bufsize = buffersize; buffer = new char[buffersize]; nextCharBuf = new byte[buffersize]; bufline = new int[buffersize]; bufcolumn = new int[buffersize]; } public ASCII_UCodeESC_CharStream(java.io.InputStream dstream, int startline, int startcolumn) { inputStream = dstream; line = startline; column = startcolumn - 1; available = bufsize = 4096; buffer = new char[4096]; nextCharBuf = new byte[4096]; bufline = new int[4096]; bufcolumn = new int[4096]; } public final String GetImage() { if (bufpos >= tokenBegin) return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); else return new String(buffer, tokenBegin, bufsize - tokenBegin) + new String(buffer, 0, bufpos + 1); } public void Done() { nextCharBuf = null; buffer = null; bufline = null; bufcolumn = null; } }