/****************************************************************************** * Copyright (C) 2015 Fabio Zadrozny and others * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Fabio Zadrozny <fabiofz@gmail.com> - initial API and implementation ******************************************************************************/ package org.python.pydev.shared_ui.search; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.python.pydev.shared_core.string.FastStringBuffer; /** * A string pattern matcher supporting * and ? */ public class StringMatcherWithIndexSemantics { private final Pattern compiled; private boolean startsWithWildCard; private boolean endsWithWildCard; public StringMatcherWithIndexSemantics(String text, boolean ignoreCase, boolean wholeWord) { FastStringBuffer buf = new FastStringBuffer(); FastStringBuffer finalRegexp = new FastStringBuffer(); boolean skipLeftSep = false; boolean skipRightSep = false; if (!wholeWord) { skipLeftSep = true; } while (text.startsWith("*")) { skipLeftSep = true; text = text.substring(1); } if (!wholeWord) { skipRightSep = true; } while (text.endsWith("*") && !text.endsWith("\\*")) { skipRightSep = true; text = text.substring(0, text.length() - 1); } int length = text.length(); for (int i = 0; i < length; i++) { char c = text.charAt(i); if (c == '\\') { i++; if (i < length) { //Will be quoted buf.append(text.charAt(i)); } continue; } if (c == '*' || c == '?') { if (buf.length() > 0) { finalRegexp.append(Pattern.quote(buf.toString())); buf.clear(); } finalRegexp.append(".").append(c); } else { buf.append(c); } } if (buf.length() > 0) { finalRegexp.append(Pattern.quote(buf.toString())); } if (!skipLeftSep) { if (!finalRegexp.startsWith('*')) { if (!finalRegexp.startsWith("\\Q")) { finalRegexp.insert(0, "\\b"); } else { if (Character.isJavaIdentifierPart(finalRegexp.charAt(2))) { finalRegexp.insert(0, "\\b"); } } } } if (!skipRightSep) { if (!finalRegexp.endsWith('*')) { if (!finalRegexp.endsWith("\\E")) { finalRegexp.append("\\b"); } else { if (Character.isJavaIdentifierPart(finalRegexp.charAt(finalRegexp.length() - 3))) { finalRegexp.append("\\b"); } } } } this.startsWithWildCard = skipLeftSep; this.endsWithWildCard = skipRightSep; compiled = Pattern.compile(finalRegexp.toString(), ignoreCase ? Pattern.CASE_INSENSITIVE : 0); } public static class Position { public int start; //inclusive public int end; //exclusive public Position(int start, int end) { this.start = start; this.end = end; } public int getStart() { return start; } public int getEnd() { return end; } } public Position find(String text, int start) { if (text == null) { throw new IllegalArgumentException(); } if (start < 0) { start = 0; } Matcher matcher = compiled.matcher(text); boolean find = matcher.find(start); if (!find) { return null; } else { int startPos = matcher.start(); int endPos = matcher.end(); return new Position(startPos, endPos); } } public boolean match(String text) { Matcher matcher = compiled.matcher(text); if (!startsWithWildCard && !endsWithWildCard) { return matcher.matches(); } else { Position found = this.find(text, 0); if (found == null) { return false; } if (!startsWithWildCard && found.start != 0) { return false; } if (!endsWithWildCard && found.end != text.length()) { return false; } return true; } } }