1 12 package org.eclipse.team.internal.ccvs.core.util; 13 14 import java.util.Vector ; 15 import java.util.HashMap ; 16 17 24 public class StringMatcher { 25 26 protected static class CharacterClass { 27 final boolean isNegated; 28 final String text; 29 30 CharacterClass(boolean isNegated, String text) { 31 this.isNegated = isNegated; 32 this.text = text; 33 } 34 35 boolean listed(char c) { 36 for (int i = 0; i < text.length(); ) { 37 if (i + 2 < text.length() && text.charAt(i + 1) == '-') { 38 if (c >= text.charAt(i) && c <= text.charAt(i + 2)) 39 return true; 40 i += 3; 41 } else { 42 if (c == text.charAt(i)) 43 return true; 44 i++; 45 } 46 } 47 return false; 48 } 49 boolean match(char c) { 50 return listed(c) ^ isNegated; 51 } 52 } 53 54 protected String fPattern; 55 protected int fLength; protected boolean fIgnoreWildCards; 57 protected boolean fIgnoreCase; 58 protected boolean fHasLeadingStar; 59 protected boolean fHasTrailingStar; 60 protected String fSegments[]; protected HashMap fCharacterClassMaps[]; 62 63 64 protected int fBound = 0; 65 66 67 protected static final char fSingleWildCard = '\u0000'; 68 69 public static class Position { 70 int start; int end; public Position(int start, int end) { 73 this.start = start; 74 this.end = end; 75 } 76 public int getStart() { 77 return start; 78 } 79 public int getEnd() { 80 return end; 81 } 82 } 83 84 97 public StringMatcher.Position find(String text, int start, int end) { 98 if (fPattern == null|| text == null) 99 throw new IllegalArgumentException (); 100 101 int tlen = text.length(); 102 if (start < 0) 103 start = 0; 104 if (end > tlen) 105 end = tlen; 106 if (end < 0 ||start >= end ) 107 return null; 108 if (fLength == 0) 109 return new Position(start, start); 110 if (fIgnoreWildCards) { 111 int x = posIn(text, start, end); 112 if (x < 0) 113 return null; 114 return new Position(x, x+fLength); 115 } 116 117 int segCount = fSegments.length; 118 if (segCount == 0) return new Position (start, end); 120 121 int curPos = start; 122 int matchStart = -1; 123 int i; 124 for (i = 0; i < segCount && curPos < end; ++i) { 125 String current = fSegments[i]; 126 int nextMatch = regExpPosIn(text, curPos, end, current, fCharacterClassMaps[i]); 127 if (nextMatch < 0 ) 128 return null; 129 if(i == 0) 130 matchStart = nextMatch; 131 curPos = nextMatch + current.length(); 132 } 133 if (i < segCount) 134 return null; 135 return new Position(matchStart, curPos); 136 } 137 138 164 public StringMatcher(String aPattern, boolean ignoreCase, boolean ignoreWildCards) { 165 fIgnoreCase = ignoreCase; 166 fIgnoreWildCards = ignoreWildCards; 167 fLength = aPattern.length(); 168 169 170 if (fIgnoreCase) { 171 fPattern = aPattern.toUpperCase(); 172 } else { 173 fPattern = aPattern; 174 } 175 176 if (fIgnoreWildCards) { 177 parseNoWildCards(); 178 } else { 179 parseWildCards(); 180 } 181 } 182 190 public boolean match(String text, int start, int end) { 191 if (null == text) 192 throw new IllegalArgumentException (); 193 194 if (start > end) 195 return false; 196 197 if (fIgnoreWildCards) 198 return (end - start == fLength) && fPattern.regionMatches(fIgnoreCase, 0, text, start, fLength); 199 int segCount= fSegments.length; 200 if (segCount == 0 && (fHasLeadingStar || fHasTrailingStar)) return true; 202 if (start == end) 203 return fLength == 0; 204 if (fLength == 0) 205 return start == end; 206 207 int tlen= text.length(); 208 if (start < 0) 209 start= 0; 210 if (end > tlen) 211 end= tlen; 212 213 int tCurPos= start; 214 int bound= end - fBound; 215 if ( bound < 0) 216 return false; 217 int i=0; 218 String current= fSegments[i]; 219 HashMap curCharClassMap= fCharacterClassMaps[i]; 220 int segLength= current.length(); 221 222 223 if (!fHasLeadingStar){ 224 if(!regExpRegionMatches(text, start, current, 0, segLength, curCharClassMap)) { 225 return false; 226 } else { 227 ++i; 228 tCurPos= tCurPos + segLength; 229 } 230 } 231 if ((fSegments.length == 1) && (!fHasLeadingStar) && (!fHasTrailingStar)) { 232 return tCurPos == end; 234 } 235 236 while (i < segCount) { 237 current= fSegments[i]; 238 curCharClassMap= fCharacterClassMaps[i]; 239 int currentMatch; 240 int k= current.indexOf(fSingleWildCard); 241 if (k < 0) { 242 currentMatch= textPosIn(text, tCurPos, end, current); 243 if (currentMatch < 0) 244 return false; 245 } else { 246 currentMatch= regExpPosIn(text, tCurPos, end, current, curCharClassMap); 247 if (currentMatch < 0) 248 return false; 249 } 250 tCurPos= currentMatch + current.length(); 251 i++; 252 } 253 254 255 if (!fHasTrailingStar && tCurPos != end) { 256 int clen= current.length(); 257 return regExpRegionMatches(text, end - clen, current, 0, clen, curCharClassMap); 258 } 259 return i == segCount ; 260 } 261 266 public boolean match(String text) { 267 return match(text, 0, text.length()); 268 } 269 273 private void parseNoWildCards() { 274 fSegments = new String [1]; 275 fSegments[0] = fPattern; 276 fBound = fLength; 277 } 278 282 private void parseWildCards() { 283 if(fPattern.startsWith("*")) fHasLeadingStar = true; 285 286 Vector temp = new Vector (); 287 HashMap segmentCCs = null; 288 Vector allCCs = new Vector (); 289 290 int pos = 0; 291 StringBuffer buf = new StringBuffer (); 292 while (pos < fLength) { 293 char c = fPattern.charAt(pos++); 294 fHasTrailingStar = false; 295 switch (c) { 296 case '\\': 297 if (pos >= fLength) { 298 buf.append(c); 299 } else { 300 c = fPattern.charAt(pos++); 301 buf.append(c); 302 } 303 break; 304 case '*': 305 fHasTrailingStar = true; 306 if (buf.length() > 0) { 307 308 temp.addElement(buf.toString()); 309 allCCs.addElement(segmentCCs); 310 fBound += buf.length(); 311 buf.setLength(0); 312 segmentCCs = null; 313 } 314 break; 315 case '[': 316 if (segmentCCs == null) 317 segmentCCs = new HashMap (); 318 if (pos >= fLength) { 319 buf.append(c); 321 break; 322 } 323 boolean negated = (fPattern.charAt(pos) == '!'); 324 int beginPos = (negated ? pos + 1 : pos); 325 int endPos = fPattern.indexOf(']', beginPos + 1); 326 if (endPos == -1) { 327 buf.append(c); 329 break; 330 } 331 CharacterClass cc = new CharacterClass(negated, fPattern.substring(beginPos, endPos)); 332 segmentCCs.put(new Integer (buf.length()), cc); 333 pos = endPos + 1; 334 335 case '?': 336 337 buf.append(fSingleWildCard); 338 break; 339 default: 340 buf.append(c); 341 } 342 } 343 344 345 if (buf.length() > 0) { 346 temp.addElement(buf.toString()); 347 allCCs.addElement(segmentCCs); 348 fBound += buf.length(); 349 } 350 351 fSegments = new String [temp.size()]; 352 temp.copyInto(fSegments); 353 fCharacterClassMaps = new HashMap [allCCs.size()]; 354 allCCs.copyInto(fCharacterClassMaps); 355 } 356 362 protected int posIn(String text, int start, int end) { return textPosIn(text, start, end, fPattern); 364 } 365 373 protected int regExpPosIn(String text, int start, int end, String p, HashMap ccMap) { 374 int plen = p.length(); 375 376 int max = end - plen; 377 for (int i = start; i <= max; ++i) { 378 if (regExpRegionMatches(text, i, p, 0, plen, ccMap)) 379 return i; 380 } 381 return -1; 382 } 383 394 protected boolean regExpRegionMatches(String text, int tStart, String p, int pStart, int plen, HashMap ccMap) { 395 for (int ppos = 0; plen-- > 0; ppos++) { 396 char tchar = text.charAt(tStart++); 397 char pchar = p.charAt(pStart++); 398 399 400 if (!fIgnoreWildCards) { 401 402 if (pchar == fSingleWildCard) { 403 if (ccMap == null) 404 continue; 405 CharacterClass cc = (CharacterClass) ccMap.get(new Integer (ppos)); 406 if (cc == null || cc.match(tchar)) 407 continue; 408 else 409 return false; 410 } 411 } 412 if (pchar == tchar) 413 continue; 414 if (fIgnoreCase) { 415 char tc = Character.toUpperCase(tchar); 416 if (tc == pchar) 417 continue; 418 } 419 return false; 420 } 421 return true; 422 } 423 431 protected int textPosIn(String text, int start, int end, String p) { 432 433 int plen = p.length(); 434 int max = end - plen; 435 436 if (!fIgnoreCase) { 437 int i = text.indexOf(p, start); 438 if (i == -1 || i > max) 439 return -1; 440 return i; 441 } 442 443 for (int i = start; i <= max; ++i) { 444 if (text.regionMatches(true, i, p, 0, plen)) 445 return i; 446 } 447 448 return -1; 449 } 450 } 451 | Popular Tags |