KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > gjt > sp > jedit > syntax > KeywordMap


1 /*
2  * KeywordMap.java - Fast keyword->id map
3  * :tabSize=8:indentSize=8:noTabs=false:
4  * :folding=explicit:collapseFolds=1:
5  *
6  * Copyright (C) 1998, 2002 Slava Pestov
7  * Copyright (C) 1999 Mike Dillon
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22  */

23 package org.gjt.sp.jedit.syntax;
24
25 import javax.swing.text.Segment JavaDoc;
26 import java.util.Vector JavaDoc;
27
28 /**
29  * A <code>KeywordMap</code> is similar to a hashtable in that it maps keys
30  * to values. However, the `keys' are Swing segments. This allows lookups of
31  * text substrings without the overhead of creating a new string object.
32  *
33  * @author Slava Pestov, Mike Dillon
34  * @version $Id: KeywordMap.java 5053 2004-05-29 01:55:26Z spestov $
35  */

36 public class KeywordMap
37 {
38     //{{{ KeywordMap constructor
39
/**
40      * Creates a new <code>KeywordMap</code>.
41      * @param ignoreCase True if keys are case insensitive
42      */

43     public KeywordMap(boolean ignoreCase)
44     {
45         this(ignoreCase, 52);
46         this.ignoreCase = ignoreCase;
47         noWordSep = new StringBuffer JavaDoc();
48     } //}}}
49

50     //{{{ KeywordMap constructor
51
/**
52      * Creates a new <code>KeywordMap</code>.
53      * @param ignoreCase True if the keys are case insensitive
54      * @param mapLength The number of `buckets' to create.
55      * A value of 52 will give good performance for most maps.
56      */

57     public KeywordMap(boolean ignoreCase, int mapLength)
58     {
59         this.mapLength = mapLength;
60         this.ignoreCase = ignoreCase;
61         map = new Keyword[mapLength];
62     } //}}}
63

64     //{{{ lookup() method
65
/**
66      * Looks up a key.
67      * @param text The text segment
68      * @param offset The offset of the substring within the text segment
69      * @param length The length of the substring
70      */

71     public byte lookup(Segment JavaDoc text, int offset, int length)
72     {
73         if(length == 0)
74             return Token.NULL;
75         Keyword k = map[getSegmentMapKey(text, offset, length)];
76         while(k != null)
77         {
78             if(length != k.keyword.length)
79             {
80                 k = k.next;
81                 continue;
82             }
83             if(SyntaxUtilities.regionMatches(ignoreCase,text,offset,
84                 k.keyword))
85                 return k.id;
86             k = k.next;
87         }
88         return Token.NULL;
89     } //}}}
90

91     //{{{ add() method
92
/**
93      * Adds a key-value mapping.
94      * @param keyword The key
95      * @param id The value
96      */

97     public void add(String JavaDoc keyword, byte id)
98     {
99         add(keyword.toCharArray(),id);
100     } //}}}
101

102     //{{{ add() method
103
/**
104      * Adds a key-value mapping.
105      * @param keyword The key
106      * @param id The value
107      * @since jEdit 4.2pre3
108      */

109     public void add(char[] keyword, byte id)
110     {
111         int key = getStringMapKey(keyword);
112
113         // complete-word command needs a list of all non-alphanumeric
114
// characters used in a keyword map.
115
loop: for(int i = 0; i < keyword.length; i++)
116         {
117             char ch = keyword[i];
118             if(!Character.isLetterOrDigit(ch))
119             {
120                 for(int j = 0; j < noWordSep.length(); j++)
121                 {
122                     if(noWordSep.charAt(j) == ch)
123                         continue loop;
124                 }
125
126                 noWordSep.append(ch);
127             }
128         }
129
130         map[key] = new Keyword(keyword,id,map[key]);
131     } //}}}
132

133     //{{{ getNonAlphaNumericChars() method
134
/**
135      * Returns all non-alphanumeric characters that appear in the
136      * keywords of this keyword map.
137      * @since jEdit 4.0pre3
138      */

139     public String JavaDoc getNonAlphaNumericChars()
140     {
141         return noWordSep.toString();
142     } //}}}
143

144     //{{{ getKeywords() method
145
/**
146      * Returns an array containing all keywords in this keyword map.
147      * @since jEdit 4.0pre3
148      */

149     public String JavaDoc[] getKeywords()
150     {
151         Vector JavaDoc vector = new Vector JavaDoc(100);
152         for(int i = 0; i < map.length; i++)
153         {
154             Keyword keyword = map[i];
155             while(keyword != null)
156             {
157                 vector.addElement(new String JavaDoc(keyword.keyword));
158                 keyword = keyword.next;
159             }
160         }
161         String JavaDoc[] retVal = new String JavaDoc[vector.size()];
162         vector.copyInto(retVal);
163         return retVal;
164     } //}}}
165

166     //{{{ getIgnoreCase() method
167
/**
168      * Returns true if the keyword map is set to be case insensitive,
169      * false otherwise.
170      */

171     public boolean getIgnoreCase()
172     {
173         return ignoreCase;
174     } //}}}
175

176     //{{{ setIgnoreCase() method
177
/**
178      * Sets if the keyword map should be case insensitive.
179      * @param ignoreCase True if the keyword map should be case
180      * insensitive, false otherwise
181      */

182     public void setIgnoreCase(boolean ignoreCase)
183     {
184         this.ignoreCase = ignoreCase;
185     } //}}}
186

187     //{{{ add() method
188
/**
189      * Adds the content of another keyword map to this one.
190      * @since jEdit 4.2pre3
191      */

192     public void add(KeywordMap map)
193     {
194         for(int i = 0; i < map.map.length; i++)
195         {
196             Keyword k = map.map[i];
197             while(k != null)
198             {
199                 add(k.keyword,k.id);
200                 k = k.next;
201             }
202         }
203     } //}}}
204

205     //{{{ Private members
206

207     //{{{ Instance variables
208
private int mapLength;
209     private Keyword[] map;
210     private boolean ignoreCase;
211     private StringBuffer JavaDoc noWordSep;
212     //}}}
213

214     //{{{ getStringMapKey() method
215
private int getStringMapKey(char[] s)
216     {
217         return (Character.toUpperCase(s[0]) +
218                 Character.toUpperCase(s[s.length-1]))
219                 % mapLength;
220     } //}}}
221

222     //{{{ getSegmentMapKey() method
223
protected int getSegmentMapKey(Segment JavaDoc s, int off, int len)
224     {
225         return (Character.toUpperCase(s.array[off]) +
226                 Character.toUpperCase(s.array[off + len - 1]))
227                 % mapLength;
228     } //}}}
229

230     //}}}
231

232     //{{{ Keyword class
233
class Keyword
234     {
235         public Keyword(char[] keyword, byte id, Keyword next)
236         {
237             this.keyword = keyword;
238             this.id = id;
239             this.next = next;
240         }
241
242         public char[] keyword;
243         public byte id;
244         public Keyword next;
245     } //}}}
246
}
247
Popular Tags