forked from I2P_Developers/i2p.i2p
Susimail: Add RegexOutputStream util
WIP, prep for enhancements to follow
This commit is contained in:
143
apps/susimail/src/src/i2p/susi/util/RegexOutputStream.java
Normal file
143
apps/susimail/src/src/i2p/susi/util/RegexOutputStream.java
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
package i2p.susi.util;
|
||||||
|
|
||||||
|
import java.io.FilterOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.data.DataHelper;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace patterns with a simple regex on the fly.
|
||||||
|
*
|
||||||
|
* @since 0.9.62
|
||||||
|
*/
|
||||||
|
public class RegexOutputStream extends FilterOutputStream {
|
||||||
|
|
||||||
|
private final String match, repl;
|
||||||
|
/** parse in progress */
|
||||||
|
private final StringBuilder buf;
|
||||||
|
private final String noMatch;
|
||||||
|
private final Log _log;
|
||||||
|
private boolean found;
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param out MUST be buffered because this writes one byte at a time
|
||||||
|
* @param pattern the only special char recognized is '*' and cannot be at the beginning or end
|
||||||
|
* or have two in a row. ASCII-only, no UTF-8.
|
||||||
|
* @param replace ASCII-only, no UTF-8.
|
||||||
|
* @param onNoMatch force output of this at the end if no replacement made, or null
|
||||||
|
*/
|
||||||
|
public RegexOutputStream(OutputStream out, String pattern, String replace, String onNoMatch) {
|
||||||
|
super(out);
|
||||||
|
if (pattern.length() == 0 || pattern.startsWith("*") || pattern.endsWith("*") || pattern.contains("**"))
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
match = pattern;
|
||||||
|
repl = replace;
|
||||||
|
noMatch = onNoMatch;
|
||||||
|
buf = new StringBuilder(64);
|
||||||
|
_log = I2PAppContext.getGlobalContext().logManager().getLog(RegexOutputStream.class);
|
||||||
|
if (_log.shouldDebug())
|
||||||
|
_log.debug("New regex replace '" + match + "' with '" + repl + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(int val) throws IOException {
|
||||||
|
char c = (char) val;
|
||||||
|
char m = match.charAt(idx);
|
||||||
|
if (c == '\r' || c == '\n') {
|
||||||
|
flushit();
|
||||||
|
out.write(val);
|
||||||
|
} else if (m == '*') {
|
||||||
|
pushit(c);
|
||||||
|
char d = match.charAt(idx + 1);
|
||||||
|
if (c == d) {
|
||||||
|
idx += 2;
|
||||||
|
if (idx == match.length()) {
|
||||||
|
replaceit();
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (m == c) {
|
||||||
|
pushit(c);
|
||||||
|
idx++;
|
||||||
|
if (idx == match.length()) {
|
||||||
|
replaceit();
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
flushit();
|
||||||
|
out.write(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* put in the pending parse buf
|
||||||
|
*/
|
||||||
|
private void pushit(char c) {
|
||||||
|
buf.append(c);
|
||||||
|
//if (_log.shouldDebug())
|
||||||
|
// _log.debug("Push, buf now '" + buf + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* flush buf to out, start over
|
||||||
|
*/
|
||||||
|
private void flushit() throws IOException {
|
||||||
|
int len = buf.length();
|
||||||
|
if (len > 0) {
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
out.write(buf.charAt(i));
|
||||||
|
}
|
||||||
|
clearit();
|
||||||
|
}
|
||||||
|
//if (_log.shouldDebug())
|
||||||
|
// _log.debug("Flush");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Throw out inbuf, output replacement, start over
|
||||||
|
*/
|
||||||
|
private void replaceit() throws IOException {
|
||||||
|
int len = repl.length();
|
||||||
|
if (len > 0) {
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
out.write(repl.charAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_log.shouldInfo())
|
||||||
|
_log.info("Replaced '" + match + "' with '" + repl + "' buf: '" + buf + "'");
|
||||||
|
clearit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start over
|
||||||
|
*/
|
||||||
|
private void clearit() {
|
||||||
|
buf.setLength(0);
|
||||||
|
idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
flushit();
|
||||||
|
if (!found && noMatch != null) {
|
||||||
|
if (_log.shouldInfo())
|
||||||
|
_log.info("No match, appending '" + noMatch + "'");
|
||||||
|
out.write(DataHelper.getASCII(noMatch));
|
||||||
|
}
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
OutputStream out = new RegexOutputStream(System.out, args[0], args[1], null);
|
||||||
|
net.i2p.data.DataHelper.copy(System.in, out);
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
****/
|
||||||
|
}
|
Reference in New Issue
Block a user