1 package org.apache.regexp; 2 3 59 60 import java.io.Serializable ; 61 import java.util.Vector ; 62 63 370 public class RE implements Serializable 371 { 372 375 public static final int MATCH_NORMAL = 0x0000; 376 377 380 public static final int MATCH_CASEINDEPENDENT = 0x0001; 381 382 385 public static final int MATCH_MULTILINE = 0x0002; 386 387 390 public static final int MATCH_SINGLELINE = 0x0004; 391 392 403 404 static final char OP_END = 'E'; static final char OP_BOL = '^'; static final char OP_EOL = '$'; static final char OP_ANY = '.'; static final char OP_ANYOF = '['; static final char OP_BRANCH = '|'; static final char OP_ATOM = 'A'; static final char OP_STAR = '*'; static final char OP_PLUS = '+'; static final char OP_MAYBE = '?'; static final char OP_ESCAPE = '\\'; static final char OP_OPEN = '('; static final char OP_OPEN_CLUSTER = '<'; static final char OP_CLOSE = ')'; static final char OP_CLOSE_CLUSTER = '>'; static final char OP_BACKREF = '#'; static final char OP_GOTO = 'G'; static final char OP_NOTHING = 'N'; static final char OP_RELUCTANTSTAR = '8'; static final char OP_RELUCTANTPLUS = '='; static final char OP_RELUCTANTMAYBE = '/'; static final char OP_POSIXCLASS = 'P'; 429 static final char E_ALNUM = 'w'; static final char E_NALNUM = 'W'; static final char E_BOUND = 'b'; static final char E_NBOUND = 'B'; static final char E_SPACE = 's'; static final char E_NSPACE = 'S'; static final char E_DIGIT = 'd'; static final char E_NDIGIT = 'D'; 439 static final char POSIX_CLASS_ALNUM = 'w'; static final char POSIX_CLASS_ALPHA = 'a'; static final char POSIX_CLASS_BLANK = 'b'; static final char POSIX_CLASS_CNTRL = 'c'; static final char POSIX_CLASS_DIGIT = 'd'; static final char POSIX_CLASS_GRAPH = 'g'; static final char POSIX_CLASS_LOWER = 'l'; static final char POSIX_CLASS_PRINT = 'p'; static final char POSIX_CLASS_PUNCT = '!'; static final char POSIX_CLASS_SPACE = 's'; static final char POSIX_CLASS_UPPER = 'u'; static final char POSIX_CLASS_XDIGIT = 'x'; static final char POSIX_CLASS_JSTART = 'j'; static final char POSIX_CLASS_JPART = 'k'; 455 static final int maxNode = 65536; static final int MAX_PAREN = 16; 459 static final int offsetOpcode = 0; static final int offsetOpdata = 1; static final int offsetNext = 2; static final int nodeSize = 3; 465 466 static final String NEWLINE = System.getProperty("line.separator"); 467 468 REProgram program; transient CharacterIterator search; int matchFlags; int maxParen = MAX_PAREN; 473 474 transient int parenCount; transient int start0; transient int end0; transient int start1; transient int end1; transient int start2; transient int end2; transient int[] startn; transient int[] endn; 485 transient int[] startBackref; transient int[] endBackref; 489 498 public RE(String pattern) throws RESyntaxException 499 { 500 this(pattern, MATCH_NORMAL); 501 } 502 503 513 public RE(String pattern, int matchFlags) throws RESyntaxException 514 { 515 this(new RECompiler().compile(pattern)); 516 setMatchFlags(matchFlags); 517 } 518 519 538 public RE(REProgram program, int matchFlags) 539 { 540 setProgram(program); 541 setMatchFlags(matchFlags); 542 } 543 544 551 public RE(REProgram program) 552 { 553 this(program, MATCH_NORMAL); 554 } 555 556 560 public RE() 561 { 562 this((REProgram)null, MATCH_NORMAL); 563 } 564 565 570 public static String simplePatternToFullRegularExpression(String pattern) 571 { 572 StringBuffer buf = new StringBuffer (); 573 for (int i = 0; i < pattern.length(); i++) 574 { 575 char c = pattern.charAt(i); 576 switch (c) 577 { 578 case '*': 579 buf.append(".*"); 580 break; 581 582 case '.': 583 case '[': 584 case ']': 585 case '\\': 586 case '+': 587 case '?': 588 case '{': 589 case '}': 590 case '$': 591 case '^': 592 case '|': 593 case '(': 594 case ')': 595 buf.append('\\'); 596 default: 597 buf.append(c); 598 break; 599 } 600 } 601 return buf.toString(); 602 } 603 604 617 public void setMatchFlags(int matchFlags) 618 { 619 this.matchFlags = matchFlags; 620 } 621 622 637 public int getMatchFlags() 638 { 639 return matchFlags; 640 } 641 642 649 public void setProgram(REProgram program) 650 { 651 this.program = program; 652 if (program != null && program.maxParens != -1) { 653 this.maxParen = program.maxParens; 654 } else { 655 this.maxParen = MAX_PAREN; 656 } 657 } 658 659 664 public REProgram getProgram() 665 { 666 return program; 667 } 668 669 673 public int getParenCount() 674 { 675 return parenCount; 676 } 677 678 683 public String getParen(int which) 684 { 685 int start; 686 if (which < parenCount && (start = getParenStart(which)) >= 0) 687 { 688 return search.substring(start, getParenEnd(which)); 689 } 690 return null; 691 } 692 693 698 public final int getParenStart(int which) 699 { 700 if (which < parenCount) 701 { 702 switch (which) 703 { 704 case 0: 705 return start0; 706 707 case 1: 708 return start1; 709 710 case 2: 711 return start2; 712 713 default: 714 if (startn == null) 715 { 716 allocParens(); 717 } 718 return startn[which]; 719 } 720 } 721 return -1; 722 } 723 724 729 public final int getParenEnd(int which) 730 { 731 if (which < parenCount) 732 { 733 switch (which) 734 { 735 case 0: 736 return end0; 737 738 case 1: 739 return end1; 740 741 case 2: 742 return end2; 743 744 default: 745 if (endn == null) 746 { 747 allocParens(); 748 } 749 return endn[which]; 750 } 751 } 752 return -1; 753 } 754 755 760 public final int getParenLength(int which) 761 { 762 if (which < parenCount) 763 { 764 return getParenEnd(which) - getParenStart(which); 765 } 766 return -1; 767 } 768 769 774 protected final void setParenStart(int which, int i) 775 { 776 if (which < parenCount) 777 { 778 switch (which) 779 { 780 case 0: 781 start0 = i; 782 break; 783 784 case 1: 785 start1 = i; 786 break; 787 788 case 2: 789 start2 = i; 790 break; 791 792 default: 793 if (startn == null) 794 { 795 allocParens(); 796 } 797 startn[which] = i; 798 break; 799 } 800 } 801 } 802 803 808 protected final void setParenEnd(int which, int i) 809 { 810 if (which < parenCount) 811 { 812 switch (which) 813 { 814 case 0: 815 end0 = i; 816 break; 817 818 case 1: 819 end1 = i; 820 break; 821 822 case 2: 823 end2 = i; 824 break; 825 826 default: 827 if (endn == null) 828 { 829 allocParens(); 830 } 831 endn[which] = i; 832 break; 833 } 834 } 835 } 836 837 843 protected void internalError(String s) throws Error 844 { 845 throw new Error ("RE internal error: " + s); 846 } 847 848 851 private final void allocParens() 852 { 853 startn = new int[maxParen]; 855 endn = new int[maxParen]; 856 857 for (int i = 0; i < maxParen; i++) 859 { 860 startn[i] = -1; 861 endn[i] = -1; 862 } 863 } 864 865 873 protected int matchNodes(int firstNode, int lastNode, int idxStart) 874 { 875 int idx = idxStart; 877 878 int next, opcode, opdata; 880 int idxNew; 881 char[] instruction = program.instruction; 882 for (int node = firstNode; node < lastNode; ) 883 { 884 opcode = instruction[node + offsetOpcode]; 885 next = node + (short)instruction[node + offsetNext]; 886 opdata = instruction[node + offsetOpdata]; 887 888 switch (opcode) 889 { 890 case OP_RELUCTANTMAYBE: 891 { 892 int once = 0; 893 do 894 { 895 if ((idxNew = matchNodes(next, maxNode, idx)) != -1) 897 { 898 return idxNew; 899 } 900 } 901 while ((once++ == 0) && (idx = matchNodes(node + nodeSize, next, idx)) != -1); 902 return -1; 903 } 904 905 case OP_RELUCTANTPLUS: 906 while ((idx = matchNodes(node + nodeSize, next, idx)) != -1) 907 { 908 if ((idxNew = matchNodes(next, maxNode, idx)) != -1) 910 { 911 return idxNew; 912 } 913 } 914 return -1; 915 916 case OP_RELUCTANTSTAR: 917 do 918 { 919 if ((idxNew = matchNodes(next, maxNode, idx)) != -1) 921 { 922 return idxNew; 923 } 924 } 925 while ((idx = matchNodes(node + nodeSize, next, idx)) != -1); 926 return -1; 927 928 case OP_OPEN: 929 930 if ((program.flags & REProgram.OPT_HASBACKREFS) != 0) 932 { 933 startBackref[opdata] = idx; 934 } 935 if ((idxNew = matchNodes(next, maxNode, idx)) != -1) 936 { 937 if ((opdata + 1) > parenCount) 939 { 940 parenCount = opdata + 1; 941 } 942 943 if (getParenStart(opdata) == -1) 945 { 946 setParenStart(opdata, idx); 947 } 948 } 949 return idxNew; 950 951 case OP_CLOSE: 952 953 if ((program.flags & REProgram.OPT_HASBACKREFS) != 0) 955 { 956 endBackref[opdata] = idx; 957 } 958 if ((idxNew = matchNodes(next, maxNode, idx)) != -1) 959 { 960 if ((opdata + 1) > parenCount) 962 { 963 parenCount = opdata + 1; 964 } 965 966 if (getParenEnd(opdata) == -1) 968 { 969 setParenEnd(opdata, idx); 970 } 971 } 972 return idxNew; 973 974 case OP_OPEN_CLUSTER: 975 case OP_CLOSE_CLUSTER: 976 return matchNodes( next, maxNode, idx ); 978 979 case OP_BACKREF: 980 { 981 int s = startBackref[opdata]; 983 int e = endBackref[opdata]; 984 985 if (s == -1 || e == -1) 987 { 988 return -1; 989 } 990 991 if (s == e) 993 { 994 break; 995 } 996 997 int l = e - s; 999 1000 if (search.isEnd(idx + l - 1)) 1002 { 1003 return -1; 1004 } 1005 1006 if ((matchFlags & MATCH_CASEINDEPENDENT) != 0) 1008 { 1009 for (int i = 0; i < l; i++) 1011 { 1012 if (Character.toLowerCase(search.charAt(idx++)) != Character.toLowerCase(search.charAt(s + i))) 1013 { 1014 return -1; 1015 } 1016 } 1017 } 1018 else 1019 { 1020 for (int i = 0; i < l; i++) 1022 { 1023 if (search.charAt(idx++) != search.charAt(s + i)) 1024 { 1025 return -1; 1026 } 1027 } 1028 } 1029 } 1030 break; 1031 1032 case OP_BOL: 1033 1034 if (idx != 0) 1036 { 1037 if ((matchFlags & MATCH_MULTILINE) == MATCH_MULTILINE) 1039 { 1040 if (idx <= 0 || !isNewline(idx - 1)) { 1042 return -1; 1043 } else { 1044 break; 1045 } 1046 } 1047 return -1; 1048 } 1049 break; 1050 1051 case OP_EOL: 1052 1053 if (!search.isEnd(0) && !search.isEnd(idx)) 1055 { 1056 if ((matchFlags & MATCH_MULTILINE) == MATCH_MULTILINE) 1058 { 1059 if (! isNewline(idx)) { 1061 return -1; 1062 } else { 1063 break; 1064 } 1065 } 1066 return -1; 1067 } 1068 break; 1069 1070 case OP_ESCAPE: 1071 1072 switch (opdata) 1074 { 1075 case E_NBOUND: 1077 case E_BOUND: 1078 { 1079 char cLast = ((idx == 0) ? '\n' : search.charAt(idx - 1)); 1080 char cNext = ((search.isEnd(idx)) ? '\n' : search.charAt(idx)); 1081 if ((Character.isLetterOrDigit(cLast) == Character.isLetterOrDigit(cNext)) == (opdata == E_BOUND)) 1082 { 1083 return -1; 1084 } 1085 } 1086 break; 1087 1088 case E_ALNUM: 1090 case E_NALNUM: 1091 case E_DIGIT: 1092 case E_NDIGIT: 1093 case E_SPACE: 1094 case E_NSPACE: 1095 1096 if (search.isEnd(idx)) 1098 { 1099 return -1; 1100 } 1101 1102 char c = search.charAt(idx); 1103 1104 switch (opdata) 1106 { 1107 case E_ALNUM: 1108 case E_NALNUM: 1109 if (!((Character.isLetterOrDigit(c) || c == '_') == (opdata == E_ALNUM))) 1110 { 1111 return -1; 1112 } 1113 break; 1114 1115 case E_DIGIT: 1116 case E_NDIGIT: 1117 if (!(Character.isDigit(c) == (opdata == E_DIGIT))) 1118 { 1119 return -1; 1120 } 1121 break; 1122 1123 case E_SPACE: 1124 case E_NSPACE: 1125 if (!(Character.isWhitespace(c) == (opdata == E_SPACE))) 1126 { 1127 return -1; 1128 } 1129 break; 1130 } 1131 idx++; 1132 break; 1133 1134 default: 1135 internalError("Unrecognized escape '" + opdata + "'"); 1136 } 1137 break; 1138 1139 case OP_ANY: 1140 1141 if((matchFlags & MATCH_SINGLELINE) == MATCH_SINGLELINE) { 1142 if(search.isEnd(idx)) 1144 { 1145 return -1; 1146 } 1147 idx++; 1148 break; 1149 } 1150 else 1151 { 1152 if (search.isEnd(idx) || search.charAt(idx++) == '\n') 1154 { 1155 return -1; 1156 } 1157 break; 1158 } 1159 1160 case OP_ATOM: 1161 { 1162 if (search.isEnd(idx)) 1164 { 1165 return -1; 1166 } 1167 1168 int lenAtom = opdata; 1170 int startAtom = node + nodeSize; 1171 1172 if (search.isEnd(lenAtom + idx - 1)) 1174 { 1175 return -1; 1176 } 1177 1178 if ((matchFlags & MATCH_CASEINDEPENDENT) != 0) 1180 { 1181 for (int i = 0; i < lenAtom; i++) 1182 { 1183 if (Character.toLowerCase(search.charAt(idx++)) != Character.toLowerCase(instruction[startAtom + i])) 1184 { 1185 return -1; 1186 } 1187 } 1188 } 1189 else 1190 { 1191 for (int i = 0; i < lenAtom; i++) 1192 { 1193 if (search.charAt(idx++) != instruction[startAtom + i]) 1194 { 1195 return -1; 1196 } 1197 } 1198 } 1199 } 1200 break; 1201 1202 case OP_POSIXCLASS: 1203 { 1204 if (search.isEnd(idx)) 1206 { 1207 return -1; 1208 } 1209 1210 switch (opdata) 1211 { 1212 case POSIX_CLASS_ALNUM: 1213 if (!Character.isLetterOrDigit(search.charAt(idx))) 1214 { 1215 return -1; 1216 } 1217 break; 1218 1219 case POSIX_CLASS_ALPHA: 1220 if (!Character.isLetter(search.charAt(idx))) 1221 { 1222 return -1; 1223 } 1224 break; 1225 1226 case POSIX_CLASS_DIGIT: 1227 if (!Character.isDigit(search.charAt(idx))) 1228 { 1229 return -1; 1230 } 1231 break; 1232 1233 case POSIX_CLASS_BLANK: if (!Character.isSpaceChar(search.charAt(idx))) 1235 { 1236 return -1; 1237 } 1238 break; 1239 1240 case POSIX_CLASS_SPACE: 1241 if (!Character.isWhitespace(search.charAt(idx))) 1242 { 1243 return -1; 1244 } 1245 break; 1246 1247 case POSIX_CLASS_CNTRL: 1248 if (Character.getType(search.charAt(idx)) != Character.CONTROL) 1249 { 1250 return -1; 1251 } 1252 break; 1253 1254 case POSIX_CLASS_GRAPH: switch (Character.getType(search.charAt(idx))) 1256 { 1257 case Character.MATH_SYMBOL: 1258 case Character.CURRENCY_SYMBOL: 1259 case Character.MODIFIER_SYMBOL: 1260 case Character.OTHER_SYMBOL: 1261 break; 1262 1263 default: 1264 return -1; 1265 } 1266 break; 1267 1268 case POSIX_CLASS_LOWER: 1269 if (Character.getType(search.charAt(idx)) != Character.LOWERCASE_LETTER) 1270 { 1271 return -1; 1272 } 1273 break; 1274 1275 case POSIX_CLASS_UPPER: 1276 if (Character.getType(search.charAt(idx)) != Character.UPPERCASE_LETTER) 1277 { 1278 return -1; 1279 } 1280 break; 1281 1282 case POSIX_CLASS_PRINT: 1283 if (Character.getType(search.charAt(idx)) == Character.CONTROL) 1284 { 1285 return -1; 1286 } 1287 break; 1288 1289 case POSIX_CLASS_PUNCT: 1290 { 1291 int type = Character.getType(search.charAt(idx)); 1292 switch(type) 1293 { 1294 case Character.DASH_PUNCTUATION: 1295 case Character.START_PUNCTUATION: 1296 case Character.END_PUNCTUATION: 1297 case Character.CONNECTOR_PUNCTUATION: 1298 case Character.OTHER_PUNCTUATION: 1299 break; 1300 1301 default: 1302 return -1; 1303 } 1304 } 1305 break; 1306 1307 case POSIX_CLASS_XDIGIT: { 1309 boolean isXDigit = ((search.charAt(idx) >= '0' && search.charAt(idx) <= '9') || 1310 (search.charAt(idx) >= 'a' && search.charAt(idx) <= 'f') || 1311 (search.charAt(idx) >= 'A' && search.charAt(idx) <= 'F')); 1312 if (!isXDigit) 1313 { 1314 return -1; 1315 } 1316 } 1317 break; 1318 1319 case POSIX_CLASS_JSTART: 1320 if (!Character.isJavaIdentifierStart(search.charAt(idx))) 1321 { 1322 return -1; 1323 } 1324 break; 1325 1326 case POSIX_CLASS_JPART: 1327 if (!Character.isJavaIdentifierPart(search.charAt(idx))) 1328 { 1329 return -1; 1330 } 1331 break; 1332 1333 default: 1334 internalError("Bad posix class"); 1335 break; 1336 } 1337 1338 idx++; 1340 } 1341 break; 1342 1343 case OP_ANYOF: 1344 { 1345 if (search.isEnd(idx)) 1347 { 1348 return -1; 1349 } 1350 1351 char c = search.charAt(idx); 1353 boolean caseFold = (matchFlags & MATCH_CASEINDEPENDENT) != 0; 1354 if (caseFold) 1355 { 1356 c = Character.toLowerCase(c); 1357 } 1358 1359 int idxRange = node + nodeSize; 1361 int idxEnd = idxRange + (opdata * 2); 1362 boolean match = false; 1363 for (int i = idxRange; i < idxEnd; ) 1364 { 1365 char s = instruction[i++]; 1367 char e = instruction[i++]; 1368 1369 if (caseFold) 1371 { 1372 s = Character.toLowerCase(s); 1373 e = Character.toLowerCase(e); 1374 } 1375 1376 if (c >= s && c <= e) 1378 { 1379 match = true; 1380 break; 1381 } 1382 } 1383 1384 if (!match) 1386 { 1387 return -1; 1388 } 1389 idx++; 1390 } 1391 break; 1392 1393 case OP_BRANCH: 1394 { 1395 if (instruction[next + offsetOpcode] != OP_BRANCH) 1397 { 1398 node += nodeSize; 1400 continue; 1401 } 1402 1403 short nextBranch; 1405 do 1406 { 1407 if ((idxNew = matchNodes(node + nodeSize, maxNode, idx)) != -1) 1409 { 1410 return idxNew; 1411 } 1412 1413 nextBranch = (short)instruction[node + offsetNext]; 1415 node += nextBranch; 1416 } 1417 while (nextBranch != 0 && (instruction[node + offsetOpcode] == OP_BRANCH)); 1418 1419 return -1; 1421 } 1422 1423 case OP_NOTHING: 1424 case OP_GOTO: 1425 1426 break; 1428 1429 case OP_END: 1430 1431 setParenEnd(0, idx); 1433 return idx; 1434 1435 default: 1436 1437 internalError("Invalid opcode '" + opcode + "'"); 1439 } 1440 1441 node = next; 1443 } 1444 1445 internalError("Corrupt program"); 1447 return -1; 1448 } 1449 1450 1457 protected boolean matchAt(int i) 1458 { 1459 start0 = -1; 1461 end0 = -1; 1462 start1 = -1; 1463 end1 = -1; 1464 start2 = -1; 1465 end2 = -1; 1466 startn = null; 1467 endn = null; 1468 parenCount = 1; 1469 setParenStart(0, i); 1470 1471 if ((program.flags & REProgram.OPT_HASBACKREFS) != 0) 1473 { 1474 startBackref = new int[maxParen]; 1475 endBackref = new int[maxParen]; 1476 } 1477 1478 int idx; 1480 if ((idx = matchNodes(0, maxNode, i)) != -1) 1481 { 1482 setParenEnd(0, idx); 1483 return true; 1484 } 1485 1486 parenCount = 0; 1488 return false; 1489 } 1490 1491 1498 public boolean match(String search, int i) 1499 { 1500 return match(new StringCharacterIterator(search), i); 1501 } 1502 1503 1510 public boolean match(CharacterIterator search, int i) 1511 { 1512 if (program == null) 1514 { 1515 internalError("No RE program to run!"); 1518 } 1519 1520 this.search = search; 1522 1523 if (program.prefix == null) 1525 { 1526 for ( ;! search.isEnd(i - 1); i++) 1528 { 1529 if (matchAt(i)) 1531 { 1532 return true; 1533 } 1534 } 1535 return false; 1536 } 1537 else 1538 { 1539 boolean caseIndependent = (matchFlags & MATCH_CASEINDEPENDENT) != 0; 1541 char[] prefix = program.prefix; 1542 for ( ;! search.isEnd(i + prefix.length - 1); i++) 1543 { 1544 boolean match = false; 1546 if (caseIndependent) 1547 match = Character.toLowerCase(search.charAt(i)) == Character.toLowerCase(prefix[0]); 1548 else 1549 match = search.charAt(i) == prefix[0]; 1550 if (match) 1551 { 1552 int firstChar = i++; 1554 int k; 1555 for (k = 1; k < prefix.length; ) 1556 { 1557 if (caseIndependent) 1559 match = Character.toLowerCase(search.charAt(i++)) == Character.toLowerCase(prefix[k++]); 1560 else 1561 match = search.charAt(i++) == prefix[k++]; 1562 if (!match) 1563 { 1564 break; 1565 } 1566 } 1567 1568 if (k == prefix.length) 1570 { 1571 if (matchAt(firstChar)) 1573 { 1574 return true; 1575 } 1576 } 1577 1578 i = firstChar; 1580 } 1581 } 1582 return false; 1583 } 1584 } 1585 1586 1591 public boolean match(String search) 1592 { 1593 return match(search, 0); 1594 } 1595 1596 1605 public String [] split(String s) 1606 { 1607 Vector v = new Vector (); 1609 1610 int pos = 0; 1612 int len = s.length(); 1613 1614 while (pos < len && match(s, pos)) 1616 { 1617 int start = getParenStart(0); 1619 1620 int newpos = getParenEnd(0); 1622 1623 if (newpos == pos) 1625 { 1626 v.addElement(s.substring(pos, start + 1)); 1627 newpos++; 1628 } 1629 else 1630 { 1631 v.addElement(s.substring(pos, start)); 1632 } 1633 1634 pos = newpos; 1636 } 1637 1638 String remainder = s.substring(pos); 1640 if (remainder.length() != 0) 1641 { 1642 v.addElement(remainder); 1643 } 1644 1645 String [] ret = new String [v.size()]; 1647 v.copyInto(ret); 1648 return ret; 1649 } 1650 1651 1655 public static final int REPLACE_ALL = 0x0000; 1656 1657 1661 public static final int REPLACE_FIRSTONLY = 0x0001; 1662 1663 1666 public static final int REPLACE_BACKREFERENCES = 0x0002; 1667 1668 1682 public String subst(String substituteIn, String substitution) 1683 { 1684 return subst(substituteIn, substitution, REPLACE_ALL); 1685 } 1686 1687 1715 public String subst(String substituteIn, String substitution, int flags) 1716 { 1717 StringBuffer ret = new StringBuffer (); 1719 1720 int pos = 0; 1722 int len = substituteIn.length(); 1723 1724 while (pos < len && match(substituteIn, pos)) 1726 { 1727 ret.append(substituteIn.substring(pos, getParenStart(0))); 1729 1730 if ((flags & REPLACE_BACKREFERENCES) != 0) 1731 { 1732 int lCurrentPosition = 0; 1734 int lLastPosition = 0; 1735 int lLength = substitution.length(); 1736 1737 while ((lCurrentPosition = substitution.indexOf("$", lCurrentPosition)) >= 0) 1738 { 1739 if ((lCurrentPosition == 0 || substitution.charAt(lCurrentPosition - 1) != '\\') 1740 && lCurrentPosition+1 < lLength) 1741 { 1742 char c = substitution.charAt(lCurrentPosition + 1); 1743 if (c >= '0' && c <= '9') 1744 { 1745 ret.append(substitution.substring(lLastPosition+2, lCurrentPosition)); 1747 1748 ret.append(getParen(c - '0')); 1752 lLastPosition = lCurrentPosition; 1753 } 1754 } 1755 1756 lCurrentPosition++; 1758 } 1759 1760 ret.append(substitution.substring(lLastPosition+2,lLength)); 1762 } 1763 else 1764 { 1765 ret.append(substitution); 1767 } 1768 1769 int newpos = getParenEnd(0); 1771 1772 if (newpos == pos) 1774 { 1775 newpos++; 1776 } 1777 1778 pos = newpos; 1780 1781 if ((flags & REPLACE_FIRSTONLY) != 0) 1783 { 1784 break; 1785 } 1786 } 1787 1788 if (pos < len) 1790 { 1791 ret.append(substituteIn.substring(pos)); 1792 } 1793 1794 return ret.toString(); 1796 } 1797 1798 1806 public String [] grep(Object [] search) 1807 { 1808 Vector v = new Vector (); 1810 1811 for (int i = 0; i < search.length; i++) 1813 { 1814 String s = search[i].toString(); 1816 1817 if (match(s)) 1819 { 1820 v.addElement(s); 1821 } 1822 } 1823 1824 String [] ret = new String [v.size()]; 1826 v.copyInto(ret); 1827 return ret; 1828 } 1829 1830 1831 private boolean isNewline(int i) { 1832 1833 if (i < NEWLINE.length() - 1) { 1834 return false; 1835 } 1836 1837 if (search.charAt(i) == '\n') { 1838 return true; 1839 } 1840 1841 for (int j = NEWLINE.length() - 1; j >= 0; j--, i--) { 1842 if (NEWLINE.charAt(j) != search.charAt(i)) { 1843 return false; 1844 } 1845 } 1846 return true; 1847 } 1848} 1849 | Popular Tags |