package org.kefirsf.bb.proc;
/**
* @author kefir
*/
public abstract class AbstractEol implements ProcPatternElement {
protected static final char[] AN = new char[]{'\n'};
protected static final char[] AR = new char[]{'\r'};
protected final boolean ghost;
public AbstractEol(boolean ghost) {
this.ghost = ghost;
}
public boolean parse(Context context, ProcPatternElement terminator) throws NestingException {
Source source = context.getSource();
int len = match(source);
if (len >= 0) {
if(!ghost) {
source.incOffset(len);
}
return true;
} else {
return false;
}
}
private int match(Source source) {
return match(source, source.getOffset());
}
public boolean isNextIn(Context context) {
return match(context.getSource()) >= 0;
}
public int findIn(Source source) {
int index = source.getOffset()-1;
do {
index++;
int n = source.findFrom(index, AN, false);
int r = source.findFrom(index, AR, false);
if (n >= 0 && r >= 0) {
index = Math.min(n, r);
} else if (n >= 0) {
index = n;
} else if (r >= 0) {
index = r;
} else {
index = source.length();
}
} while (match(source, index) < 0);
return index;
}
protected abstract int match(Source source, int index);
/**
* @param source the soruce text
* @param index current cursor position
* @return -1 if at the index there is not end of line
* 0 if it's end of text
* 1 if it's single \n or \r
* 2 if it's pair \n\r or \r\n
*/
protected int calcLength(Source source, int index) {
if (index >= source.length()) {
return 0;
} else {
char c = source.charAt(index);
if (c == '\n' || c == '\r') {
if (index + 1 < source.length()) {
char nc = source.charAt(index + 1);
if (c == '\n' && nc == '\r' || c == '\r' && nc == '\n') {
return 2;
}
}
return 1;
} else {
return -1;
}
}
}
}