package jdk.nashorn.internal.runtime.regexp.joni;
final class OptExactInfo {
static final int OPT_EXACT_MAXLEN = 24;
final MinMaxLen mmd = new MinMaxLen();
final OptAnchorInfo anchor = new OptAnchorInfo();
boolean reachEnd;
boolean ignoreCase;
final char chars[] = new char[OPT_EXACT_MAXLEN];
int length;
boolean isFull() {
return length >= OPT_EXACT_MAXLEN;
}
void clear() {
mmd.clear();
anchor.clear();
reachEnd = false;
ignoreCase = false;
length = 0;
}
void copy(final OptExactInfo other) {
mmd.copy(other.mmd);
anchor.copy(other.anchor);
reachEnd = other.reachEnd;
ignoreCase = other.ignoreCase;
length = other.length;
System.arraycopy(other.chars, 0, chars, 0, OPT_EXACT_MAXLEN);
}
void concat(final OptExactInfo other) {
if (!ignoreCase && other.ignoreCase) {
if (length >= other.length) {
return;
}
ignoreCase = true;
}
int p = 0;
final int end = p + other.length;
int i;
for (i = length; p < end;) {
if (i + 1 > OPT_EXACT_MAXLEN) {
break;
}
chars[i++] = other.chars[p++];
}
length = i;
reachEnd = (p == end ? other.reachEnd : false);
final OptAnchorInfo tmp = new OptAnchorInfo();
tmp.concat(anchor, other.anchor, 1, 1);
if (!other.reachEnd) {
tmp.rightAnchor = 0;
}
anchor.copy(tmp);
}
void concatStr(final char[] lchars, final int pp, final int end, final boolean raw) {
int i;
int p = pp;
for (i = length; p < end && i < OPT_EXACT_MAXLEN;) {
if (i + 1 > OPT_EXACT_MAXLEN) {
break;
}
chars[i++] = lchars[p++];
}
length = i;
}
void altMerge(final OptExactInfo other, final OptEnvironment env) {
if (other.length == 0 || length == 0) {
clear();
return;
}
if (!mmd.equal(other.mmd)) {
clear();
return;
}
int i;
for (i = 0; i < length && i < other.length; i++) {
if (chars[i] != other.chars[i]) {
break;
}
}
if (!other.reachEnd || i<other.length || i<length) {
reachEnd = false;
}
length = i;
ignoreCase |= other.ignoreCase;
anchor.altMerge(other.anchor);
if (!reachEnd) {
anchor.rightAnchor = 0;
}
}
void select(final OptExactInfo alt) {
int v1 = length;
int v2 = alt.length;
if (v2 == 0) {
return;
} else if (v1 == 0) {
copy(alt);
return;
} else if (v1 <= 2 && v2 <= 2) {
v2 = OptMapInfo.positionValue(chars[0] & 0xff);
v1 = OptMapInfo.positionValue(alt.chars[0] & 0xff);
if (length > 1) {
v1 += 5;
}
if (alt.length > 1) {
v2 += 5;
}
}
if (!ignoreCase) {
v1 *= 2;
}
if (!alt.ignoreCase) {
v2 *= 2;
}
if (mmd.compareDistanceValue(alt.mmd, v1, v2) > 0) {
copy(alt);
}
}
private static final int COMP_EM_BASE = 20;
int compare(final OptMapInfo m) {
if (m.value <= 0) {
return -1;
}
final int ve = COMP_EM_BASE * length * (ignoreCase ? 1 : 2);
final int vm = COMP_EM_BASE * 5 * 2 / m.value;
return mmd.compareDistanceValue(m.mmd, ve, vm);
}
}