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