Graphical bits moved into files to save jar size
[jalview.git] / src / com / stevesoft / pat / Skip.java
1 //\r
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
5 // the details.\r
6 //    -- Happy Computing!\r
7 //\r
8 package com.stevesoft.pat;\r
9 \r
10 /** This class is used internally to search ahead for some\r
11     optimized Regex objects.  It searches within a String\r
12     for occrences of a given String -- like a more flexible\r
13     version of String.indexOf.\r
14     @see com.stevesoft.pat.Skip2\r
15     @see com.stevesoft.pat.SkipBMH\r
16     */\r
17 public class Skip {\r
18     static int mkmask(int c) {\r
19         char x = (char)c;\r
20         return ~( CaseMgr.toUpperCase(x) |\r
21             CaseMgr.toLowerCase(x) |\r
22             CaseMgr.toTitleCase(x));\r
23     }\r
24     String src;\r
25     int c,mask;\r
26     int offset;\r
27     boolean ign,m1;\r
28     /** Examine a Regex to determine what String it will\r
29         attempt to skip to when searching for patterns.\r
30         Return -1 if we aren't doing this. */\r
31     public static String string(Regex r) {\r
32         return r.skipper == null ? null : r.skipper.src;\r
33     }\r
34     /** Determine the offset of the String within the pattern\r
35         that we are skipping to. Return -1 if we aren't doing\r
36         this.  */\r
37     public static int offset(Regex r) {\r
38         return r.skipper == null ? -1 : r.skipper.offset;\r
39     }\r
40     /** Initialize, give it a String to search for, tell it\r
41         whether or not to ignoreCase, and what the offset is\r
42         of the String within the String to be searched. */\r
43     public Skip(String s,boolean ign,int o) {\r
44         src = s;\r
45         c = s.charAt(0);\r
46         if(ign) {\r
47             mask = mkmask(c);\r
48         } else mask = 0;\r
49         offset = o;\r
50         this.ign = ign;\r
51         m1 = (s.length()==1);\r
52     }\r
53     /** The same as find(s,0,s.length()) */\r
54     public final int find(StringLike s) {\r
55         return find(s,0,s.length());\r
56     }\r
57     static final int min(int a,int b) { return a<b ? a : b; }\r
58     /** Searches a given region of text beginning at position start\r
59         and ending at position end for the skip object. */\r
60     public int find(StringLike s,int start,int end) {\r
61         if(start > end) return -1;\r
62         start += offset;\r
63         int vend = min(s.length()-1,end+offset);\r
64         if(mask != c) {\r
65             for(int i=start;i<=vend;i++)\r
66                 if(0 == (s.charAt(i) & mask))\r
67                     //if(m1||s.regionMatches(ign,i,src,0,src.length()) )\r
68                     if(m1||CaseMgr.regionMatches(s,ign,i,src,0,src.length()) )\r
69                         return i-offset;\r
70         } else {\r
71             for(int i=start;i<=vend;i++)\r
72                 if(c == s.charAt(i))\r
73                     //if(m1||s.regionMatches(ign,i,src,0,src.length()) )\r
74                     if(m1||CaseMgr.regionMatches(s,ign,i,src,0,src.length()) )\r
75                         return i-offset;\r
76         }\r
77         return -1;\r
78     }\r
79     static Skip findSkip(Regex r) {\r
80         return findSkip(r.thePattern,r.ignoreCase,!r.dontMatchInQuotes);\r
81     }\r
82     // look for things that can be skipped\r
83     static Skip findSkip(Pattern p,boolean ignoreCase,boolean trnc) {\r
84         StringBuffer sb = new StringBuffer();\r
85         Skip subsk = null;\r
86         int offset = 0;\r
87         int skipc = -1,skipoff=0;\r
88         for(;p != null;p = p.next) {\r
89             if(p instanceof oneChar) {\r
90                 skipc = ((oneChar)p).c;\r
91                 skipoff = offset;\r
92             }\r
93             if(p instanceof oneChar && p.next instanceof oneChar) {\r
94                 Pattern psav = p;\r
95                 sb.append(((oneChar)p).c);\r
96                 while(p.next instanceof oneChar) {\r
97                     sb.append(((oneChar)p.next).c);\r
98                     p = p.next;\r
99                 }\r
100                 String st = sb.toString();\r
101                 Skip sk=null;\r
102                 if(st.length()>2)\r
103                     sk = new SkipBMH(st,ignoreCase,offset);\r
104                 else\r
105                     sk = new Skip2(st,ignoreCase,offset);\r
106                 if(trnc && st.length()>2) { // chop out a whole string...\r
107                     psav.next = new Skipped(st.substring(1));\r
108                     psav.next.next = p.next;\r
109                     psav.next.parent = p.parent;\r
110                 }\r
111                 return sk;\r
112             } else if(p instanceof Or && ((Or)p).v.size()==1\r
113                     && !((Or)p).leftForm().equals("(?!")\r
114                     && null != (subsk=\r
115                     findSkip( (Pattern)((Or)p).v.elementAt(0),ignoreCase,trnc) )) {\r
116                 subsk.offset += offset;\r
117                 return subsk;\r
118             } else if(p.minChars().equals(p.maxChars())) {\r
119                 offset += p.minChars().intValue();\r
120             } else return skipc < 0 ? null :\r
121                 new Skip(""+(char)skipc,ignoreCase,skipoff);\r
122         }\r
123         return null;\r
124     }\r
125 }\r