001: /*
002: * @(#)Regexp.java 1.16 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.misc;
029:
030: /**
031: * A class to represent a regular expression. Only handles '*'s.
032: * @author James Gosling
033: */
034:
035: public class Regexp {
036: /** if true then the matching process ignores case. */
037: public boolean ignoreCase;
038:
039: /*
040: * regular expressions are carved into three regions: a constant string
041: * prefix, a constant string suffix, and a series of floating strings in
042: * between. In the input regular expression, they are seperated by *s
043: */
044: public String exp;
045: public String prefix, suffix;
046: public boolean exact;
047: public int prefixLen, suffixLen, totalLen;
048: public String mids[];
049:
050: /** Create a new regular expression object. The regular expression
051: is a series of constant strings seperated by *s. For example:
052: <dl>
053: <dt>*.gif <dd>Matches any string that ends in ".gif".
054: <dt>/tmp/* <dd>Matches any string that starts with "/tmp/".
055: <dt>/tmp/*.gif <dd>Matches any string that starts with "/tmp/" and ends
056: with ".gif".
057: <dt>/tmp/*new*.gif <dd>Matches any string that starts with "/tmp/"
058: and ends with ".gif" and has "new" somewhere in between.
059: </dl>
060: */
061: public Regexp(String s) {
062: exp = s;
063: int firstst = s.indexOf('*');
064: int lastst = s.lastIndexOf('*');
065: if (firstst < 0) {
066: totalLen = s.length();
067: exact = true; // no * s
068: } else {
069: prefixLen = firstst;
070: if (firstst == 0)
071: prefix = null;
072: else
073: prefix = s.substring(0, firstst);
074: suffixLen = s.length() - lastst - 1;
075: if (suffixLen == 0)
076: suffix = null;
077: else
078: suffix = s.substring(lastst + 1);
079: int nmids = 0;
080: int pos = firstst;
081: while (pos < lastst && pos >= 0) {
082: nmids++;
083: pos = s.indexOf('*', pos + 1);
084: }
085: totalLen = prefixLen + suffixLen;
086: if (nmids > 0) {
087: mids = new String[nmids];
088: pos = firstst;
089: for (int i = 0; i < nmids; i++) {
090: pos++;
091: int npos = s.indexOf('*', pos);
092: if (pos < npos) {
093: mids[i] = s.substring(pos, npos);
094: totalLen += mids[i].length();
095: }
096: pos = npos;
097: }
098: }
099: }
100: }
101:
102: /** Returns true iff the String s matches this regular expression. */
103: final boolean matches(String s) {
104: return matches(s, 0, s.length());
105: }
106:
107: /** Returns true iff the substring of s from offset for len characters
108: matches this regular expression. */
109: boolean matches(String s, int offset, int len) {
110: if (exact)
111: return len == totalLen
112: && exp.regionMatches(ignoreCase, 0, s, offset, len);
113: if (len < totalLen)
114: return false;
115: if (prefixLen > 0
116: && !prefix.regionMatches(ignoreCase, 0, s, offset,
117: prefixLen)
118: || suffixLen > 0
119: && !suffix.regionMatches(ignoreCase, 0, s, offset + len
120: - suffixLen, suffixLen))
121: return false;
122: if (mids == null)
123: return true;
124: int nmids = mids.length;
125: int spos = offset + prefixLen;
126: int limit = offset + len - suffixLen;
127: for (int i = 0; i < nmids; i++) {
128: String ms = mids[i];
129: int ml = ms.length();
130: while (spos + ml <= limit
131: && !ms.regionMatches(ignoreCase, 0, s, spos, ml))
132: spos++;
133: if (spos + ml > limit)
134: return false;
135: spos += ml;
136: }
137: return true;
138: }
139:
140: static public void main(String argv[]) {
141: Regexp r = new Regexp(argv[0]);
142: System.out.print("re=" + r + "\n");
143: r.ignoreCase = true;
144: for (int i = 1; i < argv.length; i++)
145: System.out.print("<" + argv[i] + "> " + r.matches(argv[i])
146: + "\n");
147: }
148: }
|