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