1 7 8 package java.util.regex; 9 10 11 86 87 public final class Matcher implements MatchResult { 88 89 92 Pattern parentPattern; 93 94 98 int[] groups; 99 100 105 int from, to; 106 107 110 CharSequence text; 111 112 117 static final int ENDANCHOR = 1; 118 static final int NOANCHOR = 0; 119 int acceptMode = NOANCHOR; 120 121 127 int first = -1, last = 0; 128 129 132 int oldLast = -1; 133 134 137 int lastAppendPosition = 0; 138 139 144 int[] locals; 145 146 159 boolean hitEnd; 160 161 171 boolean requireEnd; 172 173 178 boolean transparentBounds = false; 179 180 184 boolean anchoringBounds = true; 185 186 189 Matcher() { 190 } 191 192 195 Matcher(Pattern parent, CharSequence text) { 196 this.parentPattern = parent; 197 this.text = text; 198 199 int parentGroupCount = Math.max(parent.capturingGroupCount, 10); 201 groups = new int[parentGroupCount * 2]; 202 locals = new int[parent.localCount]; 203 204 reset(); 206 } 207 208 213 public Pattern pattern() { 214 return parentPattern; 215 } 216 217 224 public MatchResult toMatchResult() { 225 Matcher result = new Matcher (this.parentPattern, text.toString()); 226 result.first = this.first; 227 result.last = this.last; 228 result.groups = (int[])(this.groups.clone()); 229 return result; 230 } 231 232 248 public Matcher usePattern(Pattern newPattern) { 249 if (newPattern == null) 250 throw new IllegalArgumentException ("Pattern cannot be null"); 251 parentPattern = newPattern; 252 253 int parentGroupCount = Math.max(newPattern.capturingGroupCount, 10); 255 groups = new int[parentGroupCount * 2]; 256 locals = new int[newPattern.localCount]; 257 for (int i = 0; i < groups.length; i++) 258 groups[i] = -1; 259 for (int i = 0; i < locals.length; i++) 260 locals[i] = -1; 261 return this; 262 } 263 264 274 public Matcher reset() { 275 first = -1; 276 last = 0; 277 oldLast = -1; 278 for(int i=0; i<groups.length; i++) 279 groups[i] = -1; 280 for(int i=0; i<locals.length; i++) 281 locals[i] = -1; 282 lastAppendPosition = 0; 283 from = 0; 284 to = getTextLength(); 285 return this; 286 } 287 288 302 public Matcher reset(CharSequence input) { 303 text = input; 304 return reset(); 305 } 306 307 316 public int start() { 317 if (first < 0) 318 throw new IllegalStateException ("No match available"); 319 return first; 320 } 321 322 346 public int start(int group) { 347 if (first < 0) 348 throw new IllegalStateException ("No match available"); 349 if (group > groupCount()) 350 throw new IndexOutOfBoundsException ("No group " + group); 351 return groups[group * 2]; 352 } 353 354 363 public int end() { 364 if (first < 0) 365 throw new IllegalStateException ("No match available"); 366 return last; 367 } 368 369 393 public int end(int group) { 394 if (first < 0) 395 throw new IllegalStateException ("No match available"); 396 if (group > groupCount()) 397 throw new IndexOutOfBoundsException ("No group " + group); 398 return groups[group * 2 + 1]; 399 } 400 401 420 public String group() { 421 return group(0); 422 } 423 424 459 public String group(int group) { 460 if (first < 0) 461 throw new IllegalStateException ("No match found"); 462 if (group < 0 || group > groupCount()) 463 throw new IndexOutOfBoundsException ("No group " + group); 464 if ((groups[group*2] == -1) || (groups[group*2+1] == -1)) 465 return null; 466 return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString(); 467 } 468 469 481 public int groupCount() { 482 return parentPattern.capturingGroupCount - 1; 483 } 484 485 494 public boolean matches() { 495 return match(from, ENDANCHOR); 496 } 497 498 513 public boolean find() { 514 int nextSearchIndex = last; 515 if (nextSearchIndex == first) 516 nextSearchIndex++; 517 518 if (nextSearchIndex < from) 520 nextSearchIndex = from; 521 522 if (nextSearchIndex > to) { 524 for (int i = 0; i < groups.length; i++) 525 groups[i] = -1; 526 return false; 527 } 528 return search(nextSearchIndex); 529 } 530 531 549 public boolean find(int start) { 550 int limit = getTextLength(); 551 if ((start < 0) || (start > limit)) 552 throw new IndexOutOfBoundsException ("Illegal start index"); 553 reset(); 554 return search(start); 555 } 556 557 571 public boolean lookingAt() { 572 return match(from, NOANCHOR); 573 } 574 575 590 public static String quoteReplacement(String s) { 591 if ((s.indexOf('\\') == -1) && (s.indexOf('$') == -1)) 592 return s; 593 StringBuffer sb = new StringBuffer (); 594 for (int i=0; i<s.length(); i++) { 595 char c = s.charAt(i); 596 if (c == '\\') { 597 sb.append('\\'); sb.append('\\'); 598 } else if (c == '$') { 599 sb.append('\\'); sb.append('$'); 600 } else { 601 sb.append(c); 602 } 603 } 604 return sb.toString(); 605 } 606 607 681 public Matcher appendReplacement(StringBuffer sb, String replacement) { 682 683 if (first < 0) 685 throw new IllegalStateException ("No match available"); 686 687 int cursor = 0; 689 String s = replacement; 690 StringBuffer result = new StringBuffer (); 691 692 while (cursor < replacement.length()) { 693 char nextChar = replacement.charAt(cursor); 694 if (nextChar == '\\') { 695 cursor++; 696 nextChar = replacement.charAt(cursor); 697 result.append(nextChar); 698 cursor++; 699 } else if (nextChar == '$') { 700 cursor++; 702 703 int refNum = (int)replacement.charAt(cursor) - '0'; 705 if ((refNum < 0)||(refNum > 9)) 706 throw new IllegalArgumentException ( 707 "Illegal group reference"); 708 cursor++; 709 710 boolean done = false; 712 while (!done) { 713 if (cursor >= replacement.length()) { 714 break; 715 } 716 int nextDigit = replacement.charAt(cursor) - '0'; 717 if ((nextDigit < 0)||(nextDigit > 9)) { break; 719 } 720 int newRefNum = (refNum * 10) + nextDigit; 721 if (groupCount() < newRefNum) { 722 done = true; 723 } else { 724 refNum = newRefNum; 725 cursor++; 726 } 727 } 728 729 if (group(refNum) != null) 731 result.append(group(refNum)); 732 } else { 733 result.append(nextChar); 734 cursor++; 735 } 736 } 737 738 sb.append(getSubSequence(lastAppendPosition, first)); 740 sb.append(result.toString()); 742 743 lastAppendPosition = last; 744 return this; 745 } 746 747 761 public StringBuffer appendTail(StringBuffer sb) { 762 sb.append(getSubSequence(lastAppendPosition, getTextLength()).toString()); 763 return sb; 764 } 765 766 800 public String replaceAll(String replacement) { 801 reset(); 802 boolean result = find(); 803 if (result) { 804 StringBuffer sb = new StringBuffer (); 805 do { 806 appendReplacement(sb, replacement); 807 result = find(); 808 } while (result); 809 appendTail(sb); 810 return sb.toString(); 811 } 812 return text.toString(); 813 } 814 815 842 public String replaceFirst(String replacement) { 843 if (replacement == null) 844 throw new NullPointerException ("replacement"); 845 StringBuffer sb = new StringBuffer (); 846 reset(); 847 if (find()) 848 appendReplacement(sb, replacement); 849 appendTail(sb); 850 return sb.toString(); 851 } 852 853 878 public Matcher region(int start, int end) { 879 if ((start < 0) || (start > getTextLength())) 880 throw new IndexOutOfBoundsException ("start"); 881 if ((end < 0) || (end > getTextLength())) 882 throw new IndexOutOfBoundsException ("end"); 883 if (start > end) 884 throw new IndexOutOfBoundsException ("start > end"); 885 reset(); 886 from = start; 887 to = end; 888 return this; 889 } 890 891 900 public int regionStart() { 901 return from; 902 } 903 904 913 public int regionEnd() { 914 return to; 915 } 916 917 934 public boolean hasTransparentBounds() { 935 return transparentBounds; 936 } 937 938 964 public Matcher useTransparentBounds(boolean b) { 965 transparentBounds = b; 966 return this; 967 } 968 969 985 public boolean hasAnchoringBounds() { 986 return anchoringBounds; 987 } 988 989 1010 public Matcher useAnchoringBounds(boolean b) { 1011 anchoringBounds = b; 1012 return this; 1013 } 1014 1015 1023 public String toString() { 1024 StringBuffer sb = new StringBuffer (); 1025 sb.append("java.util.regex.Matcher"); 1026 sb.append("[pattern=" + pattern()); 1027 sb.append(" region="); 1028 sb.append(regionStart() + "," + regionEnd()); 1029 sb.append(" lastmatch="); 1030 if ((first >= 0) && (group() != null)) { 1031 sb.append(group()); 1032 } 1033 sb.append("]"); 1034 return sb.toString(); 1035 } 1036 1037 1048 public boolean hitEnd() { 1049 return hitEnd; 1050 } 1051 1052 1066 public boolean requireEnd() { 1067 return requireEnd; 1068 } 1069 1070 1083 boolean search(int from) { 1084 this.hitEnd = false; 1085 this.requireEnd = false; 1086 from = from < 0 ? 0 : from; 1087 this.first = from; 1088 this.oldLast = oldLast < 0 ? from : oldLast; 1089 for (int i = 0; i < groups.length; i++) 1090 groups[i] = -1; 1091 acceptMode = NOANCHOR; 1092 boolean result = parentPattern.root.match(this, from, text); 1093 if (!result) 1094 this.first = -1; 1095 this.oldLast = this.last; 1096 return result; 1097 } 1098 1099 1105 boolean match(int from, int anchor) { 1106 this.hitEnd = false; 1107 this.requireEnd = false; 1108 from = from < 0 ? 0 : from; 1109 this.first = from; 1110 this.oldLast = oldLast < 0 ? from : oldLast; 1111 for (int i = 0; i < groups.length; i++) 1112 groups[i] = -1; 1113 acceptMode = anchor; 1114 boolean result = parentPattern.matchRoot.match(this, from, text); 1115 if (!result) 1116 this.first = -1; 1117 this.oldLast = this.last; 1118 return result; 1119 } 1120 1121 1126 int getTextLength() { 1127 return text.length(); 1128 } 1129 1130 1137 CharSequence getSubSequence(int beginIndex, int endIndex) { 1138 return text.subSequence(beginIndex, endIndex); 1139 } 1140 1141 1146 char charAt(int i) { 1147 return text.charAt(i); 1148 } 1149 1150} 1151 | Popular Tags |