/* * This file is part of MoleculeViewer. * * MoleculeViewer is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MoleculeViewer is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with MoleculeViewer. If not, see <http://www.gnu.org/licenses/>. */ package astex; /* Matcher - Classes for matching and comparing (String) values. * * Copyright (C) 1999 Oskar Liljeblad * Copyright (C) 1998 Timothy Gerard Endres (matchExprRecursor) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA. * */ /** Instances of this class represents a wildcard expression, * which can be matched against String objects. * * This class also provides static methods for matching wildcard * expressions. * * The following matching "features" are supported: * <p> * <ul> * <li>Asterisk (`*') for matching zero or more characters. * <li>Question match (`?') for matching any single character. * <li>Brackets (`[]') for matching any listed character. * Character ranges with `-' are allowed. Trying to match * `-', `[', or ']' in ranges is not recommended (arbitrary * results). Characters cannot be escaped within brackets. * <li>Escaping characters with backslash (`\'), removing their * special meaning. * </ul> * * @author Timothy Gerard Endres (matchExprRecursor method) * @author Oskar Liljeblad (everything else) */ class match { /** This flag represents the asterisk (`*') wildcard character. */ private static final int ASTERISK = 1 << 0; /** This flag represents the question mark (`?') wildcard * character. */ private static final int QUESTION_MARK = 1 << 1; /** This flag represents the bracket (`[..]') matching feature. */ private static final int BRACKETS = 1 << 2; /** This flag represents escaping feature, using backslash (`\'). */ private static final int BACKSLASH = 1 << 3; /** The default matching constructs (<tt>ASTERISK</tt>, * <tt>QUESTION_MARK</tt>, and <tt>BRACKETS</tt>). */ private static final int DEFAULT = ASTERISK|QUESTION_MARK|BRACKETS|BACKSLASH; /** Return true if string matches pattern. */ public static boolean matches(String pattern, String string) { return matchExprRecursor(string, pattern, 0, 0, DEFAULT); } /** * An internal routine to implement expression matching. * This routine is based on a self-recursive algorithm. * * <p> * This method was copied from * {@link org.gjt.util.Globber org.gjt.util.Globber}, * which is copyright (c) 1998 by Timothy Gerard Endres. * The method has been reformatted and slightly modified. * * <p> * @param string The string to be compared. * @param pattern The expression to compare <em>string</em> to. * @param sIdx The index of where we are in <em>string</em>. * @param pIdx The index of where we are in <em>pattern</em>. * @return <tt>true</tt> if <em>string</em> matched pattern, else false. */ private static boolean matchExprRecursor(String string, String pattern, int sIdx, int pIdx, int types) { int pLen = pattern.length(); int sLen = string.length(); while (true) { if (pIdx >= pLen) { return (sIdx >= sLen); } if (sIdx >= sLen && pattern.charAt(pIdx) != '*') { return false; } /* Check for a '*' as the next pattern char. * This is handled by a recursive call for * each postfix of the name. */ if ((types & ASTERISK) != 0 && pattern.charAt(pIdx) == '*') { pIdx++; if (pIdx >= pLen) return true; while (true) { if (matchExprRecursor(string, pattern, sIdx, pIdx, types)) return true; if (sIdx >= sLen) return false; sIdx++; } } /* Check for '?' as the next pattern char. * This matches the current character. */ if ((types & QUESTION_MARK) != 0 && pattern.charAt(pIdx) == '?') { pIdx++; sIdx++; continue; } /* Check for '[' as the next pattern char. * This is a list of acceptable characters, * which can include character ranges. */ if ((types & BRACKETS) != 0 && pattern.charAt(pIdx) == '[') { for (pIdx++ ; ; pIdx++) { if (pIdx >= pLen || pattern.charAt(pIdx) == ']') return false; if (pattern.charAt(pIdx) == string.charAt(sIdx)) { /* Increase so that the for loop below won't stop at * `]' of this is what we matched. * - Oskar */ pIdx++; break; } /* If `]' was the first matching character * */ if (pIdx < (pLen-1) && pattern.charAt(pIdx+1) == '-') { if (pIdx >= (pLen-2) || pattern.charAt(pIdx+2) == ']') return false; char chStr = string.charAt(sIdx); char chPtn = pattern.charAt(pIdx); char chPtn2 = pattern.charAt(pIdx+2); if ((chPtn <= chStr) && (chPtn2 >= chStr)) break; if ((chPtn >= chStr) && (chPtn2 <= chStr)) break; pIdx += 2; } } for ( ; pattern.charAt(pIdx) != ']' ; pIdx++) { if (pIdx >= pLen) { pIdx--; break; } } pIdx++; sIdx++; continue; } /* Check for backslash escapes * We just skip over them to match the next char. */ if ((types & BACKSLASH) != 0 && pattern.charAt(pIdx) == '\\') { pIdx++; if (pIdx >= pLen) return false; } if(pIdx < pLen && sIdx < sLen && pattern.charAt(pIdx) != string.charAt(sIdx)) return false; pIdx++; sIdx++; } } }