PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/eclipse_SDK-3.7.1/plugins/org.eclipse.ui.navigator.source_3.5.100.v20110809-2227/org/eclipse/ui/internal/navigator/StringMatcher.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 492 lines | 291 code | 51 blank | 150 comment | 102 complexity | e1d9063e59868b31cd2a4211a91b084f MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright (c) 2000, 2006 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * IBM Corporation - initial API and implementation
  10. *******************************************************************************/
  11. package org.eclipse.ui.internal.navigator;
  12. import java.util.Vector;
  13. /**
  14. * A string pattern matcher, suppporting "*" and "?" wildcards.
  15. */
  16. public class StringMatcher {
  17. protected String fPattern;
  18. protected int fLength; // pattern length
  19. protected boolean fIgnoreWildCards;
  20. protected boolean fIgnoreCase;
  21. protected boolean fHasLeadingStar;
  22. protected boolean fHasTrailingStar;
  23. protected String fSegments[]; // the given pattern is split into *
  24. // separated segments
  25. /* boundary value beyond which we don't need to search in the text */
  26. protected int fBound = 0;
  27. protected static final char fSingleWildCard = '\u0000';
  28. /**
  29. *
  30. */
  31. static class Position {
  32. int start; // inclusive
  33. int end; // exclusive
  34. Position(int start, int end) {
  35. this.start = start;
  36. this.end = end;
  37. }
  38. int getStart() {
  39. return start;
  40. }
  41. int getEnd() {
  42. return end;
  43. }
  44. }
  45. /**
  46. * StringMatcher constructor takes in a String object that is a simple
  47. * pattern which may contain '*' for 0 and many characters and '?' for
  48. * exactly one character.
  49. *
  50. * Literal '*' and '?' characters must be escaped in the pattern e.g., "\*"
  51. * means literal "*", etc.
  52. *
  53. * Escaping any other character (including the escape character itself),
  54. * just results in that character in the pattern. e.g., "\a" means "a" and
  55. * "\\" means "\"
  56. *
  57. * If invoking the StringMatcher with string literals in Java, don't forget
  58. * escape characters are represented by "\\".
  59. *
  60. * @param pattern
  61. * the pattern to match text against
  62. * @param ignoreCase
  63. * if true, case is ignored
  64. * @param ignoreWildCards
  65. * if true, wild cards and their escape sequences are ignored
  66. * (everything is taken literally).
  67. */
  68. public StringMatcher(String pattern, boolean ignoreCase,
  69. boolean ignoreWildCards) {
  70. if (pattern == null) {
  71. throw new IllegalArgumentException();
  72. }
  73. fIgnoreCase = ignoreCase;
  74. fIgnoreWildCards = ignoreWildCards;
  75. fPattern = pattern;
  76. fLength = pattern.length();
  77. if (fIgnoreWildCards) {
  78. parseNoWildCards();
  79. } else {
  80. parseWildCards();
  81. }
  82. }
  83. /**
  84. * Find the first occurrence of the pattern between
  85. * <code>start</code)(inclusive)
  86. * and <code>end</code>(exclusive).
  87. * @param text the String object to search in
  88. * @param start the starting index of the search range, inclusive
  89. * @param end the ending index of the search range, exclusive
  90. * @return an <code>StringMatcher.Position</code> object that keeps the starting
  91. * (inclusive) and ending positions (exclusive) of the first occurrence of the
  92. * pattern in the specified range of the text; return null if not found or subtext
  93. * is empty (start==end). A pair of zeros is returned if pattern is empty string
  94. * Note that for pattern like "*abc*" with leading and trailing stars, position of "abc"
  95. * is returned. For a pattern like"*??*" in text "abcdf", (1,3) is returned
  96. */
  97. public StringMatcher.Position find(String text, int start, int end) {
  98. if (text == null) {
  99. throw new IllegalArgumentException();
  100. }
  101. int tlen = text.length();
  102. if (start < 0) {
  103. start = 0;
  104. }
  105. if (end > tlen) {
  106. end = tlen;
  107. }
  108. if (end < 0 || start >= end) {
  109. return null;
  110. }
  111. if (fLength == 0) {
  112. return new Position(start, start);
  113. }
  114. if (fIgnoreWildCards) {
  115. int x = posIn(text, start, end);
  116. if (x < 0) {
  117. return null;
  118. }
  119. return new Position(x, x + fLength);
  120. }
  121. int segCount = fSegments.length;
  122. if (segCount == 0) {
  123. return new Position(start, end);
  124. }
  125. int curPos = start;
  126. int matchStart = -1;
  127. int i;
  128. for (i = 0; i < segCount && curPos < end; ++i) {
  129. String current = fSegments[i];
  130. int nextMatch = regExpPosIn(text, curPos, end, current);
  131. if (nextMatch < 0) {
  132. return null;
  133. }
  134. if (i == 0) {
  135. matchStart = nextMatch;
  136. }
  137. curPos = nextMatch + current.length();
  138. }
  139. if (i < segCount) {
  140. return null;
  141. }
  142. return new Position(matchStart, curPos);
  143. }
  144. /**
  145. * match the given <code>text</code> with the pattern
  146. *
  147. * @return true if matched eitherwise false
  148. * @param text
  149. * a String object
  150. */
  151. public boolean match(String text) {
  152. if (text == null) {
  153. return false;
  154. }
  155. return match(text, 0, text.length());
  156. }
  157. /**
  158. * Given the starting (inclusive) and the ending (exclusive) positions in
  159. * the <code>text</code>, determine if the given substring matches with
  160. * aPattern
  161. *
  162. * @return true if the specified portion of the text matches the pattern
  163. * @param text
  164. * a String object that contains the substring to match
  165. * @param start
  166. * marks the starting position (inclusive) of the substring
  167. * @param end
  168. * marks the ending index (exclusive) of the substring
  169. */
  170. public boolean match(String text, int start, int end) {
  171. if (null == text) {
  172. throw new IllegalArgumentException();
  173. }
  174. if (start > end) {
  175. return false;
  176. }
  177. if (fIgnoreWildCards) {
  178. return (end - start == fLength)
  179. && fPattern.regionMatches(fIgnoreCase, 0, text, start,
  180. fLength);
  181. }
  182. int segCount = fSegments.length;
  183. if (segCount == 0 && (fHasLeadingStar || fHasTrailingStar)) {
  184. // contains
  185. // only
  186. // '*'(s)
  187. return true;
  188. }
  189. if (start == end) {
  190. return fLength == 0;
  191. }
  192. if (fLength == 0) {
  193. return start == end;
  194. }
  195. int tlen = text.length();
  196. if (start < 0) {
  197. start = 0;
  198. }
  199. if (end > tlen) {
  200. end = tlen;
  201. }
  202. int tCurPos = start;
  203. int bound = end - fBound;
  204. if (bound < 0) {
  205. return false;
  206. }
  207. int i = 0;
  208. String current = fSegments[i];
  209. int segLength = current.length();
  210. /* process first segment */
  211. if (!fHasLeadingStar) {
  212. if (!regExpRegionMatches(text, start, current, 0, segLength)) {
  213. return false;
  214. }
  215. ++i;
  216. tCurPos = tCurPos + segLength;
  217. }
  218. if ((fSegments.length == 1) && (!fHasLeadingStar)
  219. && (!fHasTrailingStar)) {
  220. // only one segment to match, no wildcards specified
  221. return tCurPos == end;
  222. }
  223. /* process middle segments */
  224. while (i < segCount) {
  225. current = fSegments[i];
  226. int currentMatch;
  227. int k = current.indexOf(fSingleWildCard);
  228. if (k < 0) {
  229. currentMatch = textPosIn(text, tCurPos, end, current);
  230. if (currentMatch < 0) {
  231. return false;
  232. }
  233. } else {
  234. currentMatch = regExpPosIn(text, tCurPos, end, current);
  235. if (currentMatch < 0) {
  236. return false;
  237. }
  238. }
  239. tCurPos = currentMatch + current.length();
  240. i++;
  241. }
  242. /* process final segment */
  243. if (!fHasTrailingStar && tCurPos != end) {
  244. int clen = current.length();
  245. return regExpRegionMatches(text, end - clen, current, 0, clen);
  246. }
  247. return i == segCount;
  248. }
  249. /**
  250. * This method parses the given pattern into segments seperated by wildcard
  251. * '*' characters. Since wildcards are not being used in this case, the
  252. * pattern consists of a single segment.
  253. */
  254. private void parseNoWildCards() {
  255. fSegments = new String[1];
  256. fSegments[0] = fPattern;
  257. fBound = fLength;
  258. }
  259. /**
  260. * Parses the given pattern into segments seperated by wildcard '*'
  261. * characters.
  262. *
  263. */
  264. private void parseWildCards() {
  265. if (fPattern.startsWith("*")) { //$NON-NLS-1$
  266. fHasLeadingStar = true;
  267. }
  268. if (fPattern.endsWith("*")) {//$NON-NLS-1$
  269. /* make sure it's not an escaped wildcard */
  270. if (fLength > 1 && fPattern.charAt(fLength - 2) != '\\') {
  271. fHasTrailingStar = true;
  272. }
  273. }
  274. Vector temp = new Vector();
  275. int pos = 0;
  276. StringBuffer buf = new StringBuffer();
  277. while (pos < fLength) {
  278. char c = fPattern.charAt(pos++);
  279. switch (c) {
  280. case '\\':
  281. if (pos >= fLength) {
  282. buf.append(c);
  283. } else {
  284. char next = fPattern.charAt(pos++);
  285. /* if it's an escape sequence */
  286. if (next == '*' || next == '?' || next == '\\') {
  287. buf.append(next);
  288. } else {
  289. /* not an escape sequence, just insert literally */
  290. buf.append(c);
  291. buf.append(next);
  292. }
  293. }
  294. break;
  295. case '*':
  296. if (buf.length() > 0) {
  297. /* new segment */
  298. temp.addElement(buf.toString());
  299. fBound += buf.length();
  300. buf.setLength(0);
  301. }
  302. break;
  303. case '?':
  304. /* append special character representing single match wildcard */
  305. buf.append(fSingleWildCard);
  306. break;
  307. default:
  308. buf.append(c);
  309. }
  310. }
  311. /* add last buffer to segment list */
  312. if (buf.length() > 0) {
  313. temp.addElement(buf.toString());
  314. fBound += buf.length();
  315. }
  316. fSegments = new String[temp.size()];
  317. temp.copyInto(fSegments);
  318. }
  319. /**
  320. * @param text
  321. * a string which contains no wildcard
  322. * @param start
  323. * the starting index in the text for search, inclusive
  324. * @param end
  325. * the stopping point of search, exclusive
  326. * @return the starting index in the text of the pattern , or -1 if not
  327. * found
  328. */
  329. protected int posIn(String text, int start, int end) {// no wild card in
  330. // pattern
  331. int max = end - fLength;
  332. if (!fIgnoreCase) {
  333. int i = text.indexOf(fPattern, start);
  334. if (i == -1 || i > max) {
  335. return -1;
  336. }
  337. return i;
  338. }
  339. for (int i = start; i <= max; ++i) {
  340. if (text.regionMatches(true, i, fPattern, 0, fLength)) {
  341. return i;
  342. }
  343. }
  344. return -1;
  345. }
  346. /**
  347. * @param text
  348. * a simple regular expression that may only contain '?'(s)
  349. * @param start
  350. * the starting index in the text for search, inclusive
  351. * @param end
  352. * the stopping point of search, exclusive
  353. * @param p
  354. * a simple regular expression that may contains '?'
  355. * @return the starting index in the text of the pattern , or -1 if not
  356. * found
  357. */
  358. protected int regExpPosIn(String text, int start, int end, String p) {
  359. int plen = p.length();
  360. int max = end - plen;
  361. for (int i = start; i <= max; ++i) {
  362. if (regExpRegionMatches(text, i, p, 0, plen)) {
  363. return i;
  364. }
  365. }
  366. return -1;
  367. }
  368. /**
  369. *
  370. * @return boolean
  371. * @param text
  372. * a String to match
  373. * @param tStart
  374. * indicates the starting index of match, inclusive
  375. * @param p
  376. * a simple regular expression that may contain '?'
  377. * @param pStart
  378. * @param plen
  379. */
  380. protected boolean regExpRegionMatches(String text, int tStart, String p,
  381. int pStart, int plen) {
  382. while (plen-- > 0) {
  383. char tchar = text.charAt(tStart++);
  384. char pchar = p.charAt(pStart++);
  385. /* process wild cards */
  386. if (!fIgnoreWildCards) {
  387. /* skip single wild cards */
  388. if (pchar == fSingleWildCard) {
  389. continue;
  390. }
  391. }
  392. if (pchar == tchar) {
  393. continue;
  394. }
  395. if (fIgnoreCase) {
  396. if (Character.toUpperCase(tchar) == Character
  397. .toUpperCase(pchar)) {
  398. continue;
  399. }
  400. // comparing after converting to upper case doesn't handle all
  401. // cases;
  402. // also compare after converting to lower case
  403. if (Character.toLowerCase(tchar) == Character
  404. .toLowerCase(pchar)) {
  405. continue;
  406. }
  407. }
  408. return false;
  409. }
  410. return true;
  411. }
  412. /**
  413. * @param text
  414. * the string to match
  415. * @param start
  416. * the starting index in the text for search, inclusive
  417. * @param end
  418. * the stopping point of search, exclusive
  419. * @param p
  420. * a string that has no wildcard
  421. * @return the starting index in the text of the pattern , or -1 if not
  422. * found
  423. */
  424. protected int textPosIn(String text, int start, int end, String p) {
  425. int plen = p.length();
  426. int max = end - plen;
  427. if (!fIgnoreCase) {
  428. int i = text.indexOf(p, start);
  429. if (i == -1 || i > max) {
  430. return -1;
  431. }
  432. return i;
  433. }
  434. for (int i = start; i <= max; ++i) {
  435. if (text.regionMatches(true, i, p, 0, plen)) {
  436. return i;
  437. }
  438. }
  439. return -1;
  440. }
  441. }