| /* |
| * Permission is hereby granted, free of charge, to any person obtaining a copy of |
| * this software and associated documentation files (the "Software"), to deal in |
| * the Software without restriction, including without limitation the rights to |
| * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
| * of the Software, and to permit persons to whom the Software is furnished to do |
| * so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included in all |
| * copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| * SOFTWARE. |
| */ |
| 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; /* avoid */ |
| } |
| ignoreCase = true; |
| } |
| |
| int p = 0; // add->s; |
| 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); |
| } |
| |
| // ?? raw is not used here |
| 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) { |
| /* ByteValTable[x] is big value --> low price */ |
| 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); |
| } |
| } |
| |
| // comp_opt_exact_or_map_info |
| 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); |
| } |
| } |