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 MinMaxLen {
23    int min; /* min byte length */
24    int max; /* max byte length */
25
26    MinMaxLen() {
27    }
28
29    MinMaxLen(final int min, final int max) {
30        this.min = min;
31        this.max = max;
32    }
33
34    /* 1000 / (min-max-dist + 1) */
35    private static final short distValues[] = {
36        1000,  500,  333,  250,  200,  167,  143,  125,  111,  100,
37          91,   83,   77,   71,   67,   63,   59,   56,   53,   50,
38          48,   45,   43,   42,   40,   38,   37,   36,   34,   33,
39          32,   31,   30,   29,   29,   28,   27,   26,   26,   25,
40          24,   24,   23,   23,   22,   22,   21,   21,   20,   20,
41          20,   19,   19,   19,   18,   18,   18,   17,   17,   17,
42          16,   16,   16,   16,   15,   15,   15,   15,   14,   14,
43          14,   14,   14,   14,   13,   13,   13,   13,   13,   13,
44          12,   12,   12,   12,   12,   12,   11,   11,   11,   11,
45          11,   11,   11,   11,   11,   10,   10,   10,   10,   10
46    };
47
48    int distanceValue() {
49        if (max == INFINITE_DISTANCE) {
50            return 0;
51        }
52        final int d = max - min;
53        /* return dist_vals[d] * 16 / (mm->min + 12); */
54        return d < distValues.length ? distValues[d] : 1;
55    }
56
57    int compareDistanceValue(final MinMaxLen other, final int v1p, final int v2p) {
58        int v1 = v1p, v2 = v2p;
59
60        if (v2 <= 0) {
61            return -1;
62        }
63        if (v1 <= 0) {
64            return 1;
65        }
66
67        v1 *= distanceValue();
68        v2 *= other.distanceValue();
69
70        if (v2 > v1) {
71            return 1;
72        }
73        if (v2 < v1) {
74            return -1;
75        }
76
77        if (other.min < min) {
78            return 1;
79        }
80        if (other.min > min) {
81            return -1;
82        }
83        return 0;
84    }
85
86    boolean equal(final MinMaxLen other) {
87        return min == other.min && max == other.max;
88    }
89
90    void set(final int min, final int max) {
91        this.min = min;
92        this.max = max;
93    }
94
95    void clear() {
96        min = max = 0;
97    }
98
99    void copy(final MinMaxLen other) {
100        min = other.min;
101        max = other.max;
102    }
103
104    void add(final MinMaxLen other) {
105        min = distanceAdd(min, other.min);
106        max = distanceAdd(max, other.max);
107    }
108
109    void addLength(final int len) {
110        min = distanceAdd(min, len);
111        max = distanceAdd(max, len);
112    }
113
114    void altMerge(final MinMaxLen other) {
115        if (min > other.min) {
116            min = other.min;
117        }
118        if (max < other.max) {
119            max = other.max;
120        }
121    }
122
123    static final int INFINITE_DISTANCE = 0x7FFFFFFF;
124    static int distanceAdd(final int d1, final int d2) {
125        if (d1 == INFINITE_DISTANCE || d2 == INFINITE_DISTANCE) {
126            return INFINITE_DISTANCE;
127        }
128        if (d1 <= INFINITE_DISTANCE - d2) {
129            return d1 + d2;
130        }
131        return INFINITE_DISTANCE;
132    }
133
134    static int distanceMultiply(final int d, final int m) {
135        if (m == 0) {
136            return 0;
137        }
138        if (d < INFINITE_DISTANCE / m) {
139            return d * m;
140        }
141        return INFINITE_DISTANCE;
142    }
143
144    static String distanceRangeToString(final int a, final int b) {
145        String s = "";
146        if (a == INFINITE_DISTANCE) {
147            s += "inf";
148        } else {
149            s += "(" + a + ")";
150        }
151
152        s += "-";
153
154        if (b == INFINITE_DISTANCE) {
155            s += "inf";
156        } else {
157            s += "(" + b + ")";
158        }
159        return s;
160    }
161}
162