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 */ 20 package jdk.nashorn.internal.runtime.regexp.joni; 21 22 @SuppressWarnings("javadoc") 23 public abstract class SearchAlgorithm { 24 25 public abstract String getName(); 26 public abstract int search(Regex regex, char[] text, int textP, int textEnd, int textRange); 27 public abstract int searchBackward(Regex regex, char[] text, int textP, int adjustText, int textEnd, int textStart, int s_, int range_); 28 29 30 public static final SearchAlgorithm NONE = new SearchAlgorithm() { 31 32 @Override 33 public final String getName() { 34 return "NONE"; 35 } 36 37 @Override 38 public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) { 39 return textP; 40 } 41 42 @Override 43 public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) { 44 return textP; 45 } 46 47 }; 48 49 public static final SearchAlgorithm SLOW = new SearchAlgorithm() { 50 51 @Override 52 public final String getName() { 53 return "EXACT"; 54 } 55 56 @Override 57 public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) { 58 final char[] target = regex.exact; 59 final int targetP = regex.exactP; 60 final int targetEnd = regex.exactEnd; 61 62 63 int end = textEnd; 64 end -= targetEnd - targetP - 1; 65 66 if (end > textRange) { 67 end = textRange; 68 } 69 70 int s = textP; 71 72 while (s < end) { 73 if (text[s] == target[targetP]) { 74 int p = s + 1; 75 int t = targetP + 1; 76 while (t < targetEnd) { 77 if (target[t] != text[p++]) { 78 break; 79 } 80 t++; 81 } 82 83 if (t == targetEnd) { 84 return s; 85 } 86 } 87 s++; 88 } 89 90 return -1; 91 } 92 93 @Override 94 public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) { 95 final char[] target = regex.exact; 96 final int targetP = regex.exactP; 97 final int targetEnd = regex.exactEnd; 98 99 int s = textEnd; 100 s -= targetEnd - targetP; 101 102 if (s > textStart) { 103 s = textStart; 104 } 105 106 while (s >= textP) { 107 if (text[s] == target[targetP]) { 108 int p = s + 1; 109 int t = targetP + 1; 110 while (t < targetEnd) { 111 if (target[t] != text[p++]) { 112 break; 113 } 114 t++; 115 } 116 if (t == targetEnd) { 117 return s; 118 } 119 } 120 // s = enc.prevCharHead or s = s <= adjustText ? -1 : s - 1; 121 s--; 122 } 123 return -1; 124 } 125 }; 126 127 public static final class SLOW_IC extends SearchAlgorithm { 128 public SLOW_IC(final Regex regex) { 129 //empty 130 } 131 132 @Override 133 public final String getName() { 134 return "EXACT_IC"; 135 } 136 137 @Override 138 public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) { 139 final char[] target = regex.exact; 140 final int targetP = regex.exactP; 141 final int targetEnd = regex.exactEnd; 142 143 int end = textEnd; 144 end -= targetEnd - targetP - 1; 145 146 if (end > textRange) { 147 end = textRange; 148 } 149 int s = textP; 150 151 while (s < end) { 152 if (lowerCaseMatch(target, targetP, targetEnd, text, s, textEnd)) { 153 return s; 154 } 155 s++; 156 } 157 return -1; 158 } 159 160 @Override 161 public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) { 162 final char[] target = regex.exact; 163 final int targetP = regex.exactP; 164 final int targetEnd = regex.exactEnd; 165 166 int s = textEnd; 167 s -= targetEnd - targetP; 168 169 if (s > textStart) { 170 s = textStart; 171 } 172 173 while (s >= textP) { 174 if (lowerCaseMatch(target, targetP, targetEnd, text, s, textEnd)) { 175 return s; 176 } 177 s = EncodingHelper.prevCharHead(adjustText, s); 178 } 179 return -1; 180 } 181 182 private static boolean lowerCaseMatch(final char[] t, final int tPp, final int tEnd, 183 final char[] chars, final int pp, final int end) { 184 185 for (int tP = tPp, p = pp; tP < tEnd; ) { 186 if (t[tP++] != EncodingHelper.toLowerCase(chars[p++])) { 187 return false; 188 } 189 } 190 return true; 191 } 192 } 193 194 public static final SearchAlgorithm BM = new SearchAlgorithm() { 195 196 @Override 197 public final String getName() { 198 return "EXACT_BM"; 199 } 200 201 @Override 202 public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) { 203 final char[] target = regex.exact; 204 final int targetP = regex.exactP; 205 final int targetEnd = regex.exactEnd; 206 207 int end = textRange + (targetEnd - targetP) - 1; 208 if (end > textEnd) { 209 end = textEnd; 210 } 211 212 final int tail = targetEnd - 1; 213 int s = textP + (targetEnd - targetP) - 1; 214 215 if (regex.intMap == null) { 216 while (s < end) { 217 int p = s; 218 int t = tail; 219 220 while (text[p] == target[t]) { 221 if (t == targetP) { 222 return p; 223 } 224 p--; t--; 225 } 226 227 s += regex.map[text[s] & 0xff]; 228 } 229 } else { /* see int_map[] */ 230 while (s < end) { 231 int p = s; 232 int t = tail; 233 234 while (text[p] == target[t]) { 235 if (t == targetP) { 236 return p; 237 } 238 p--; t--; 239 } 240 241 s += regex.intMap[text[s] & 0xff]; 242 } 243 } 244 return -1; 245 } 246 247 private static final int BM_BACKWARD_SEARCH_LENGTH_THRESHOLD = 100; 248 249 @Override 250 public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) { 251 final char[] target = regex.exact; 252 final int targetP = regex.exactP; 253 final int targetEnd = regex.exactEnd; 254 255 if (regex.intMapBackward == null) { 256 if (s_ - range_ < BM_BACKWARD_SEARCH_LENGTH_THRESHOLD) { 257 // goto exact_method; 258 return SLOW.searchBackward(regex, text, textP, adjustText, textEnd, textStart, s_, range_); 259 } 260 setBmBackwardSkip(regex, target, targetP, targetEnd); 261 } 262 263 int s = textEnd - (targetEnd - targetP); 264 265 if (textStart < s) { 266 s = textStart; 267 } 268 269 while (s >= textP) { 270 int p = s; 271 int t = targetP; 272 while (t < targetEnd && text[p] == target[t]) { 273 p++; t++; 274 } 275 if (t == targetEnd) { 276 return s; 277 } 278 279 s -= regex.intMapBackward[text[s] & 0xff]; 280 } 281 return -1; 282 } 283 284 285 private void setBmBackwardSkip(final Regex regex, final char[] chars, final int p, final int end) { 286 int[] skip; 287 if (regex.intMapBackward == null) { 288 skip = new int[Config.CHAR_TABLE_SIZE]; 289 regex.intMapBackward = skip; 290 } else { 291 skip = regex.intMapBackward; 292 } 293 294 final int len = end - p; 295 296 for (int i=0; i<Config.CHAR_TABLE_SIZE; i++) { 297 skip[i] = len; 298 } 299 for (int i=len-1; i>0; i--) { 300 skip[chars[i] & 0xff] = i; 301 } 302 } 303 }; 304 305 public static final SearchAlgorithm MAP = new SearchAlgorithm() { 306 307 @Override 308 public final String getName() { 309 return "MAP"; 310 } 311 312 @Override 313 public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) { 314 final byte[] map = regex.map; 315 int s = textP; 316 317 while (s < textRange) { 318 if (text[s] > 0xff || map[text[s]] != 0) { 319 return s; 320 } 321 s++; 322 } 323 return -1; 324 } 325 326 @Override 327 public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) { 328 final byte[] map = regex.map; 329 int s = textStart; 330 331 if (s >= textEnd) { 332 s = textEnd - 1; 333 } 334 while (s >= textP) { 335 if (text[s] > 0xff || map[text[s]] != 0) { 336 return s; 337 } 338 s--; 339 } 340 return -1; 341 } 342 }; 343 344 }