2 // This software is now distributed according to
\r
3 // the Lesser Gnu Public License. Please see
\r
4 // http://www.gnu.org/copyleft/lesser.txt for
\r
6 // -- Happy Computing!
\r
8 package com.stevesoft.pat;
\r
11 * This class is used internally to search ahead for some optimized Regex
\r
12 * objects. It searches within a String for occrences of a given String -- like
\r
13 * a more flexible version of String.indexOf.
\r
15 * @see com.stevesoft.pat.Skip2
\r
16 * @see com.stevesoft.pat.SkipBMH
\r
20 static int mkmask(int c)
\r
23 return ~(CaseMgr.toUpperCase(x) | CaseMgr.toLowerCase(x) | CaseMgr
\r
36 * Examine a Regex to determine what String it will attempt to skip to when
\r
37 * searching for patterns. Return -1 if we aren't doing this.
\r
39 public static String string(Regex r)
\r
41 return r.skipper == null ? null : r.skipper.src;
\r
45 * Determine the offset of the String within the pattern that we are skipping
\r
46 * to. Return -1 if we aren't doing this.
\r
48 public static int offset(Regex r)
\r
50 return r.skipper == null ? -1 : r.skipper.offset;
\r
54 * Initialize, give it a String to search for, tell it whether or not to
\r
55 * ignoreCase, and what the offset is of the String within the String to be
\r
58 public Skip(String s, boolean ign, int o)
\r
72 m1 = (s.length() == 1);
\r
75 /** The same as find(s,0,s.length()) */
\r
76 public final int find(StringLike s)
\r
78 return find(s, 0, s.length());
\r
81 static final int min(int a, int b)
\r
83 return a < b ? a : b;
\r
87 * Searches a given region of text beginning at position start and ending at
\r
88 * position end for the skip object.
\r
90 public int find(StringLike s, int start, int end)
\r
97 int vend = min(s.length() - 1, end + offset);
\r
100 for (int i = start; i <= vend; i++)
\r
102 if (0 == (s.charAt(i) & mask))
\r
104 // if(m1||s.regionMatches(ign,i,src,0,src.length()) )
\r
105 if (m1 || CaseMgr.regionMatches(s, ign, i, src, 0, src.length()))
\r
114 for (int i = start; i <= vend; i++)
\r
116 if (c == s.charAt(i))
\r
118 // if(m1||s.regionMatches(ign,i,src,0,src.length()) )
\r
119 if (m1 || CaseMgr.regionMatches(s, ign, i, src, 0, src.length()))
\r
129 static Skip findSkip(Regex r)
\r
131 return findSkip(r.thePattern, r.ignoreCase, !r.dontMatchInQuotes);
\r
134 // look for things that can be skipped
\r
135 static Skip findSkip(Pattern p, boolean ignoreCase, boolean trnc)
\r
137 javajs.util.SB sb = new javajs.util.SB();
\r
140 int skipc = -1, skipoff = 0;
\r
141 for (; p != null; p = p.next)
\r
143 if (p instanceof oneChar)
\r
145 skipc = ((oneChar) p).c;
\r
148 if (p instanceof oneChar && p.next instanceof oneChar)
\r
151 sb.appendC(((oneChar) p).c);
\r
152 while (p.next instanceof oneChar)
\r
154 sb.appendC(((oneChar) p.next).c);
\r
157 String st = sb.toString();
\r
159 if (st.length() > 2)
\r
161 sk = new SkipBMH(st, ignoreCase, offset);
\r
165 sk = new Skip2(st, ignoreCase, offset);
\r
167 if (trnc && st.length() > 2)
\r
168 { // chop out a whole string...
\r
169 psav.next = new Skipped(st.substring(1));
\r
170 psav.next.next = p.next;
\r
171 psav.next.parent = p.parent;
\r
175 else if (p instanceof Or
\r
176 && ((Or) p).v.size() == 1
\r
177 && !((Or) p).leftForm().equals("(?!")
\r
178 && null != (subsk = findSkip((Pattern) ((Or) p).v
\r
179 .elementAt(0), ignoreCase, trnc)))
\r
181 subsk.offset += offset;
\r
184 else if (p.minChars().equals(p.maxChars()))
\r
186 offset += p.minChars().intValue();
\r
190 return skipc < 0 ? null : new Skip("" + (char) skipc, ignoreCase,
\r