OptExactInfo.java revision 1088:7e62d98d4625
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) {
60                return; /* avoid */
61            }
62            ignoreCase = true;
63        }
64
65        int p = 0; // add->s;
66        final int end = p + other.length;
67
68        int i;
69        for (i = length; p < end;) {
70            if (i + 1 > OPT_EXACT_MAXLEN) {
71                break;
72            }
73            chars[i++] = other.chars[p++];
74        }
75
76        length = i;
77        reachEnd = (p == end ? other.reachEnd : false);
78
79        final OptAnchorInfo tmp = new OptAnchorInfo();
80        tmp.concat(anchor, other.anchor, 1, 1);
81        if (!other.reachEnd) {
82            tmp.rightAnchor = 0;
83        }
84        anchor.copy(tmp);
85    }
86
87    // ?? raw is not used here
88    void concatStr(final char[] lchars, final int pp, final int end, final boolean raw) {
89        int i;
90        int p = pp;
91        for (i = length; p < end && i < OPT_EXACT_MAXLEN;) {
92            if (i + 1 > OPT_EXACT_MAXLEN) {
93                break;
94            }
95            chars[i++] = lchars[p++];
96        }
97
98        length = i;
99    }
100
101    void altMerge(final OptExactInfo other, final OptEnvironment env) {
102        if (other.length == 0 || length == 0) {
103            clear();
104            return;
105        }
106
107        if (!mmd.equal(other.mmd)) {
108            clear();
109            return;
110        }
111
112        int i;
113        for (i = 0; i < length && i < other.length; i++) {
114            if (chars[i] != other.chars[i]) {
115                break;
116            }
117        }
118
119        if (!other.reachEnd || i<other.length || i<length) {
120            reachEnd = false;
121        }
122
123        length = i;
124        ignoreCase |= other.ignoreCase;
125
126        anchor.altMerge(other.anchor);
127
128        if (!reachEnd) {
129            anchor.rightAnchor = 0;
130        }
131    }
132
133
134    void select(final OptExactInfo alt) {
135        int v1 = length;
136        int v2 = alt.length;
137
138        if (v2 == 0) {
139            return;
140        } else if (v1 == 0) {
141            copy(alt);
142            return;
143        } else if (v1 <= 2 && v2 <= 2) {
144            /* ByteValTable[x] is big value --> low price */
145            v2 = OptMapInfo.positionValue(chars[0] & 0xff);
146            v1 = OptMapInfo.positionValue(alt.chars[0] & 0xff);
147
148            if (length > 1) {
149                v1 += 5;
150            }
151            if (alt.length > 1) {
152                v2 += 5;
153            }
154        }
155
156        if (!ignoreCase) {
157            v1 *= 2;
158        }
159        if (!alt.ignoreCase) {
160            v2 *= 2;
161        }
162
163        if (mmd.compareDistanceValue(alt.mmd, v1, v2) > 0) {
164            copy(alt);
165        }
166    }
167
168    // comp_opt_exact_or_map_info
169    private static final int COMP_EM_BASE   = 20;
170    int compare(final OptMapInfo m) {
171        if (m.value <= 0) {
172            return -1;
173        }
174
175        final int ve = COMP_EM_BASE * length * (ignoreCase ? 1 : 2);
176        final int vm = COMP_EM_BASE * 5 * 2 / m.value;
177
178        return mmd.compareDistanceValue(m.mmd, ve, vm);
179    }
180}
181