OptExactInfo.java revision 953:221a84ef44c0
1/*
2 * Permission is hereby granted, free of charge, to any person obtaining a copy of
3 * this software and associated documentation files (the "Software"), to deal in
4 * the Software without restriction, including without limitation the rights to
5 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
6 * of the Software, and to permit persons to whom the Software is furnished to do
7 * so, subject to the following conditions:
8 *
9 * The above copyright notice and this permission notice shall be included in all
10 * copies or substantial portions of the Software.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18 * SOFTWARE.
19 */
20package jdk.nashorn.internal.runtime.regexp.joni;
21
22final class OptExactInfo {
23    static final int OPT_EXACT_MAXLEN = 24;
24
25    final MinMaxLen mmd = new MinMaxLen();
26    final OptAnchorInfo anchor = new OptAnchorInfo();
27
28    boolean reachEnd;
29    boolean ignoreCase;
30
31    final char chars[] = new char[OPT_EXACT_MAXLEN];
32    int length;
33
34    boolean isFull() {
35        return length >= OPT_EXACT_MAXLEN;
36    }
37
38    void clear() {
39        mmd.clear();
40        anchor.clear();
41
42        reachEnd = false;
43        ignoreCase = false;
44        length = 0;
45    }
46
47    void copy(final OptExactInfo other) {
48        mmd.copy(other.mmd);
49        anchor.copy(other.anchor);
50        reachEnd = other.reachEnd;
51        ignoreCase = other.ignoreCase;
52        length = other.length;
53
54        System.arraycopy(other.chars, 0, chars, 0, OPT_EXACT_MAXLEN);
55    }
56
57    void concat(final OptExactInfo other) {
58        if (!ignoreCase && other.ignoreCase) {
59            if (length >= other.length) return; /* avoid */
60            ignoreCase = true;
61        }
62
63        int p = 0; // add->s;
64        final int end = p + other.length;
65
66        int i;
67        for (i = length; p < end;) {
68            if (i + 1 > OPT_EXACT_MAXLEN) break;
69            chars[i++] = other.chars[p++];
70        }
71
72        length = i;
73        reachEnd = (p == end ? other.reachEnd : false);
74
75        final OptAnchorInfo tmp = new OptAnchorInfo();
76        tmp.concat(anchor, other.anchor, 1, 1);
77        if (!other.reachEnd) tmp.rightAnchor = 0;
78        anchor.copy(tmp);
79    }
80
81    // ?? raw is not used here
82    void concatStr(final char[] lchars, int p, final int end, final boolean raw) {
83        int i;
84        for (i = length; p < end && i < OPT_EXACT_MAXLEN;) {
85            if (i + 1 > OPT_EXACT_MAXLEN) break;
86            chars[i++] = lchars[p++];
87        }
88
89        length = i;
90    }
91
92    void altMerge(final OptExactInfo other, final OptEnvironment env) {
93        if (other.length == 0 || length == 0) {
94            clear();
95            return;
96        }
97
98        if (!mmd.equal(other.mmd)) {
99            clear();
100            return;
101        }
102
103        int i;
104        for (i = 0; i < length && i < other.length; i++) {
105            if (chars[i] != other.chars[i]) break;
106        }
107
108        if (!other.reachEnd || i<other.length || i<length) reachEnd = false;
109
110        length = i;
111        ignoreCase |= other.ignoreCase;
112
113        anchor.altMerge(other.anchor);
114
115        if (!reachEnd) anchor.rightAnchor = 0;
116    }
117
118
119    void select(final OptExactInfo alt) {
120        int v1 = length;
121        int v2 = alt.length;
122
123        if (v2 == 0) {
124            return;
125        } else if (v1 == 0) {
126            copy(alt);
127            return;
128        } else if (v1 <= 2 && v2 <= 2) {
129            /* ByteValTable[x] is big value --> low price */
130            v2 = OptMapInfo.positionValue(chars[0] & 0xff);
131            v1 = OptMapInfo.positionValue(alt.chars[0] & 0xff);
132
133            if (length > 1) v1 += 5;
134            if (alt.length > 1) v2 += 5;
135        }
136
137        if (!ignoreCase) v1 *= 2;
138        if (!alt.ignoreCase) v2 *= 2;
139
140        if (mmd.compareDistanceValue(alt.mmd, v1, v2) > 0) copy(alt);
141    }
142
143    // comp_opt_exact_or_map_info
144    private static final int COMP_EM_BASE   = 20;
145    int compare(final OptMapInfo m) {
146        if (m.value <= 0) return -1;
147
148        final int ve = COMP_EM_BASE * length * (ignoreCase ? 1 : 2);
149        final int vm = COMP_EM_BASE * 5 * 2 / m.value;
150
151        return mmd.compareDistanceValue(m.mmd, ve, vm);
152    }
153}
154