8037781: Remove sun.misc.Regexp* classes
Reviewed-by: alanb, chegar
This commit is contained in:
parent
eb34c3be0c
commit
ae37055bc4
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.misc;
|
||||
|
||||
/**
|
||||
* A class to signal exception from the RegexpPool class.
|
||||
* @author James Gosling
|
||||
*/
|
||||
|
||||
public class REException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 4656584872733646963L;
|
||||
|
||||
REException (String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.misc;
|
||||
|
||||
/**
|
||||
* A class to represent a regular expression. Only handles '*'s.
|
||||
* @author James Gosling
|
||||
*/
|
||||
|
||||
public class Regexp {
|
||||
/** if true then the matching process ignores case. */
|
||||
public boolean ignoreCase;
|
||||
|
||||
/*
|
||||
* regular expressions are carved into three regions: a constant string
|
||||
* prefix, a constant string suffix, and a series of floating strings in
|
||||
* between. In the input regular expression, they are separated by *s
|
||||
*/
|
||||
public String exp;
|
||||
public String prefix, suffix;
|
||||
public boolean exact;
|
||||
public int prefixLen, suffixLen, totalLen;
|
||||
public String mids[];
|
||||
|
||||
/** Create a new regular expression object. The regular expression
|
||||
is a series of constant strings separated by *s. For example:
|
||||
<dl>
|
||||
<dt>*.gif <dd>Matches any string that ends in ".gif".
|
||||
<dt>/tmp/* <dd>Matches any string that starts with "/tmp/".
|
||||
<dt>/tmp/*.gif <dd>Matches any string that starts with "/tmp/" and ends
|
||||
with ".gif".
|
||||
<dt>/tmp/*new*.gif <dd>Matches any string that starts with "/tmp/"
|
||||
and ends with ".gif" and has "new" somewhere in between.
|
||||
</dl>
|
||||
*/
|
||||
public Regexp (String s) {
|
||||
exp = s;
|
||||
int firstst = s.indexOf('*');
|
||||
int lastst = s.lastIndexOf('*');
|
||||
if (firstst < 0) {
|
||||
totalLen = s.length();
|
||||
exact = true; // no * s
|
||||
} else {
|
||||
prefixLen = firstst;
|
||||
if (firstst == 0)
|
||||
prefix = null;
|
||||
else
|
||||
prefix = s.substring(0, firstst);
|
||||
suffixLen = s.length() - lastst - 1;
|
||||
if (suffixLen == 0)
|
||||
suffix = null;
|
||||
else
|
||||
suffix = s.substring(lastst + 1);
|
||||
int nmids = 0;
|
||||
int pos = firstst;
|
||||
while (pos < lastst && pos >= 0) {
|
||||
nmids++;
|
||||
pos = s.indexOf('*', pos + 1);
|
||||
}
|
||||
totalLen = prefixLen + suffixLen;
|
||||
if (nmids > 0) {
|
||||
mids = new String[nmids];
|
||||
pos = firstst;
|
||||
for (int i = 0; i < nmids; i++) {
|
||||
pos++;
|
||||
int npos = s.indexOf('*', pos);
|
||||
if (pos < npos) {
|
||||
mids[i] = s.substring(pos, npos);
|
||||
totalLen += mids[i].length();
|
||||
}
|
||||
pos = npos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true iff the String s matches this regular expression. */
|
||||
final boolean matches(String s) {
|
||||
return matches(s, 0, s.length());
|
||||
}
|
||||
|
||||
/** Returns true iff the substring of s from offset for len characters
|
||||
matches this regular expression. */
|
||||
boolean matches(String s, int offset, int len) {
|
||||
if (exact)
|
||||
return len == totalLen &&
|
||||
exp.regionMatches(ignoreCase, 0, s, offset, len);
|
||||
if (len < totalLen)
|
||||
return false;
|
||||
if (prefixLen > 0 &&
|
||||
!prefix.regionMatches(ignoreCase,
|
||||
0, s, offset, prefixLen)
|
||||
||
|
||||
suffixLen > 0 &&
|
||||
!suffix.regionMatches(ignoreCase,
|
||||
0, s, offset + len - suffixLen,
|
||||
suffixLen))
|
||||
return false;
|
||||
if (mids == null)
|
||||
return true;
|
||||
int nmids = mids.length;
|
||||
int spos = offset + prefixLen;
|
||||
int limit = offset+len-suffixLen;
|
||||
for (int i = 0; i<nmids; i++) {
|
||||
String ms = mids[i];
|
||||
int ml = ms.length();
|
||||
while (spos+ml<=limit &&
|
||||
!ms.regionMatches(ignoreCase,
|
||||
0, s, spos, ml))
|
||||
spos++;
|
||||
if (spos+ml>limit)
|
||||
return false;
|
||||
spos+=ml;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,319 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2001, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.misc;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* A class to represent a pool of regular expressions. A string
|
||||
* can be matched against the whole pool all at once. It is much
|
||||
* faster than doing individual regular expression matches one-by-one.
|
||||
*
|
||||
* @see java.misc.RegexpTarget
|
||||
* @author James Gosling
|
||||
*/
|
||||
|
||||
public class RegexpPool {
|
||||
private RegexpNode prefixMachine = new RegexpNode();
|
||||
private RegexpNode suffixMachine = new RegexpNode();
|
||||
private static final int BIG = 0x7FFFFFFF;
|
||||
private int lastDepth = BIG;
|
||||
|
||||
public RegexpPool () {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a regular expression to the pool of regular expressions.
|
||||
* @param re The regular expression to add to the pool.
|
||||
For now, only handles strings that either begin or end with
|
||||
a '*'.
|
||||
* @param ret The object to be returned when this regular expression is
|
||||
matched. If ret is an instance of the RegexpTarget class, ret.found
|
||||
is called with the string fragment that matched the '*' as its
|
||||
parameter.
|
||||
* @exception REException error
|
||||
*/
|
||||
public void add(String re, Object ret) throws REException {
|
||||
add(re, ret, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the target for the regular expression with a different
|
||||
* target.
|
||||
*
|
||||
* @param re The regular expression to be replaced in the pool.
|
||||
* For now, only handles strings that either begin or end with
|
||||
* a '*'.
|
||||
* @param ret The object to be returned when this regular expression is
|
||||
* matched. If ret is an instance of the RegexpTarget class, ret.found
|
||||
* is called with the string fragment that matched the '*' as its
|
||||
* parameter.
|
||||
*/
|
||||
public void replace(String re, Object ret) {
|
||||
try {
|
||||
add(re, ret, true);
|
||||
} catch(Exception e) {
|
||||
// should never occur if replace is true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the regular expression and its target.
|
||||
* @param re The regular expression to be deleted from the pool.
|
||||
* must begin or end with a '*'
|
||||
* @return target - the old target.
|
||||
*/
|
||||
public Object delete(String re) {
|
||||
Object o = null;
|
||||
RegexpNode p = prefixMachine;
|
||||
RegexpNode best = p;
|
||||
int len = re.length() - 1;
|
||||
int i;
|
||||
boolean prefix = true;
|
||||
|
||||
if (!re.startsWith("*") ||
|
||||
!re.endsWith("*"))
|
||||
len++;
|
||||
|
||||
if (len <= 0)
|
||||
return null;
|
||||
|
||||
/* March forward through the prefix machine */
|
||||
for (i = 0; p != null; i++) {
|
||||
if (p.result != null && p.depth < BIG
|
||||
&& (!p.exact || i == len)) {
|
||||
best = p;
|
||||
}
|
||||
if (i >= len)
|
||||
break;
|
||||
p = p.find(re.charAt(i));
|
||||
}
|
||||
|
||||
/* march backward through the suffix machine */
|
||||
p = suffixMachine;
|
||||
for (i = len; --i >= 0 && p != null;) {
|
||||
if (p.result != null && p.depth < BIG) {
|
||||
prefix = false;
|
||||
best = p;
|
||||
}
|
||||
p = p.find(re.charAt(i));
|
||||
}
|
||||
|
||||
// delete only if there is an exact match
|
||||
if (prefix) {
|
||||
if (re.equals(best.re)) {
|
||||
o = best.result;
|
||||
best.result = null;
|
||||
|
||||
}
|
||||
} else {
|
||||
if (re.equals(best.re)) {
|
||||
o = best.result;
|
||||
best.result = null;
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
/** Search for a match to a string & return the object associated
|
||||
with it with the match. When multiple regular expressions
|
||||
would match the string, the best match is returned first.
|
||||
The next best match is returned the next time matchNext is
|
||||
called.
|
||||
@param s The string to match against the regular expressions
|
||||
in the pool.
|
||||
@return null on failure, otherwise the object associated with
|
||||
the regular expression when it was added to the pool.
|
||||
If the object is an instance of RegexpTarget, then
|
||||
the return value is the result from calling
|
||||
return.found(string_that_matched_wildcard).
|
||||
*/
|
||||
public Object match(String s) {
|
||||
return matchAfter(s, BIG);
|
||||
}
|
||||
|
||||
/** Identical to match except that it will only find matches to
|
||||
regular expressions that were added to the pool <i>after</i>
|
||||
the last regular expression that matched in the last call
|
||||
to match() or matchNext() */
|
||||
public Object matchNext(String s) {
|
||||
return matchAfter(s, lastDepth);
|
||||
}
|
||||
|
||||
private void add(String re, Object ret, boolean replace) throws REException {
|
||||
int len = re.length();
|
||||
RegexpNode p;
|
||||
if (re.charAt(0) == '*') {
|
||||
p = suffixMachine;
|
||||
while (len > 1)
|
||||
p = p.add(re.charAt(--len));
|
||||
} else {
|
||||
boolean exact = false;
|
||||
if (re.charAt(len - 1) == '*')
|
||||
len--;
|
||||
else
|
||||
exact = true;
|
||||
p = prefixMachine;
|
||||
for (int i = 0; i < len; i++)
|
||||
p = p.add(re.charAt(i));
|
||||
p.exact = exact;
|
||||
}
|
||||
|
||||
if (p.result != null && !replace)
|
||||
throw new REException(re + " is a duplicate");
|
||||
|
||||
p.re = re;
|
||||
p.result = ret;
|
||||
}
|
||||
|
||||
private Object matchAfter(String s, int lastMatchDepth) {
|
||||
RegexpNode p = prefixMachine;
|
||||
RegexpNode best = p;
|
||||
int bst = 0;
|
||||
int bend = 0;
|
||||
int len = s.length();
|
||||
int i;
|
||||
if (len <= 0)
|
||||
return null;
|
||||
/* March forward through the prefix machine */
|
||||
for (i = 0; p != null; i++) {
|
||||
if (p.result != null && p.depth < lastMatchDepth
|
||||
&& (!p.exact || i == len)) {
|
||||
lastDepth = p.depth;
|
||||
best = p;
|
||||
bst = i;
|
||||
bend = len;
|
||||
}
|
||||
if (i >= len)
|
||||
break;
|
||||
p = p.find(s.charAt(i));
|
||||
}
|
||||
/* march backward through the suffix machine */
|
||||
p = suffixMachine;
|
||||
for (i = len; --i >= 0 && p != null;) {
|
||||
if (p.result != null && p.depth < lastMatchDepth) {
|
||||
lastDepth = p.depth;
|
||||
best = p;
|
||||
bst = 0;
|
||||
bend = i+1;
|
||||
}
|
||||
p = p.find(s.charAt(i));
|
||||
}
|
||||
Object o = best.result;
|
||||
if (o != null && o instanceof RegexpTarget)
|
||||
o = ((RegexpTarget) o).found(s.substring(bst, bend));
|
||||
return o;
|
||||
}
|
||||
|
||||
/** Resets the pool so that the next call to matchNext looks
|
||||
at all regular expressions in the pool. match(s); is equivalent
|
||||
to reset(); matchNext(s);
|
||||
<p><b>Multithreading note:</b> reset/nextMatch leave state in the
|
||||
regular expression pool. If multiple threads could be using this
|
||||
pool this way, they should be syncronized to avoid race hazards.
|
||||
match() was done in such a way that there are no such race
|
||||
hazards: multiple threads can be matching in the same pool
|
||||
simultaneously. */
|
||||
public void reset() {
|
||||
lastDepth = BIG;
|
||||
}
|
||||
|
||||
/** Print this pool to standard output */
|
||||
public void print(PrintStream out) {
|
||||
out.print("Regexp pool:\n");
|
||||
if (suffixMachine.firstchild != null) {
|
||||
out.print(" Suffix machine: ");
|
||||
suffixMachine.firstchild.print(out);
|
||||
out.print("\n");
|
||||
}
|
||||
if (prefixMachine.firstchild != null) {
|
||||
out.print(" Prefix machine: ");
|
||||
prefixMachine.firstchild.print(out);
|
||||
out.print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* A node in a regular expression finite state machine. */
|
||||
class RegexpNode {
|
||||
char c;
|
||||
RegexpNode firstchild;
|
||||
RegexpNode nextsibling;
|
||||
int depth;
|
||||
boolean exact;
|
||||
Object result;
|
||||
String re = null;
|
||||
|
||||
RegexpNode () {
|
||||
c = '#';
|
||||
depth = 0;
|
||||
}
|
||||
RegexpNode (char C, int depth) {
|
||||
c = C;
|
||||
this.depth = depth;
|
||||
}
|
||||
RegexpNode add(char C) {
|
||||
RegexpNode p = firstchild;
|
||||
if (p == null)
|
||||
p = new RegexpNode (C, depth+1);
|
||||
else {
|
||||
while (p != null)
|
||||
if (p.c == C)
|
||||
return p;
|
||||
else
|
||||
p = p.nextsibling;
|
||||
p = new RegexpNode (C, depth+1);
|
||||
p.nextsibling = firstchild;
|
||||
}
|
||||
firstchild = p;
|
||||
return p;
|
||||
}
|
||||
RegexpNode find(char C) {
|
||||
for (RegexpNode p = firstchild;
|
||||
p != null;
|
||||
p = p.nextsibling)
|
||||
if (p.c == C)
|
||||
return p;
|
||||
return null;
|
||||
}
|
||||
void print(PrintStream out) {
|
||||
if (nextsibling != null) {
|
||||
RegexpNode p = this;
|
||||
out.print("(");
|
||||
while (p != null) {
|
||||
out.write(p.c);
|
||||
if (p.firstchild != null)
|
||||
p.firstchild.print(out);
|
||||
p = p.nextsibling;
|
||||
out.write(p != null ? '|' : ')');
|
||||
}
|
||||
} else {
|
||||
out.write(c);
|
||||
if (firstchild != null)
|
||||
firstchild.print(out);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.misc;
|
||||
|
||||
/**
|
||||
* A class to define actions to be performed when a regular expression match
|
||||
* occurs.
|
||||
* @author James Gosling
|
||||
*/
|
||||
|
||||
public interface RegexpTarget {
|
||||
/** Gets called when a pattern in a RegexpPool matches.
|
||||
* This method is called by RegexpPool.match() who passes the return
|
||||
* value from found() back to its caller.
|
||||
* @param remainder the string that matched the * in the pattern.
|
||||
*/
|
||||
Object found(String remainder);
|
||||
}
|
Loading…
Reference in New Issue
Block a user