KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > util > CaseInsensitiveIntMap


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source 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, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.util;
30
31 /**
32  * The IntMap provides a simple hashmap from keys to integers. The API is
33  * an abbreviation of the HashMap collection API.
34  *
35  * <p>The convenience of IntMap is avoiding all the silly wrapping of
36  * integers.
37  */

38 public class CaseInsensitiveIntMap {
39   /**
40    * Encoding of a null entry. Since NULL is equal to Integer.MIN_VALUE,
41    * it's impossible to distinguish between the two.
42    */

43   public final static int NULL = 0xdeadbeef; // Integer.MIN_VALUE + 1;
44

45   private char [][]_keys;
46   private int []_values;
47   private int _size;
48   private int _mask;
49
50   /**
51    * Create a new IntMap. Default size is 256;
52    */

53   public CaseInsensitiveIntMap()
54   {
55     _keys = new char[256][];
56     _values = new int[256];
57
58     _mask = _keys.length - 1;
59     _size = 0;
60   }
61
62   /**
63    * Create a new IntMap for cloning.
64    */

65   private CaseInsensitiveIntMap(boolean dummy)
66   {
67   }
68
69   /**
70    * Clear the hashmap.
71    */

72   public void clear()
73   {
74     for (int i = 0; i < _values.length; i++) {
75       _keys[i] = null;
76       _values[i] = 0;
77     }
78     
79     _size = 0;
80   }
81   /**
82    * Returns the current number of entries in the map.
83    */

84   public int size()
85   {
86     return _size;
87   }
88
89   /**
90    * Puts a new value in the property table with the appropriate flags
91    */

92   public int get(char []key, int length)
93   {
94     if (key == null)
95       return NULL;
96
97     int hash = hash(key, length) & _mask;
98
99     while (true) {
100       char []mapKey = _keys[hash];
101
102       if (mapKey == null)
103     return NULL;
104       else if (equals(mapKey, key, length))
105     return _values[hash];
106
107       hash = (hash + 1) & _mask;
108     }
109   }
110
111   /**
112    * Puts a new value in the property table with the appropriate flags
113    */

114   public void put(char []key, int length, int value)
115   {
116     if (key == null)
117       return;
118
119     int hash = hash(key, length) & _mask;
120
121     while (true) {
122       char []testKey = _keys[hash];
123
124       if (testKey == null || equals(testKey, key, length)) {
125     _keys[hash] = new char[length];
126
127     for (int i = length - 1; i >= 0; i--) {
128       char ch = key[i];
129
130       if ('A' <= ch && ch <= 'Z')
131         ch += 'a' - 'A';
132
133       _keys[hash][i] = ch;
134     }
135     
136     _values[hash] = value;
137
138     _size++;
139
140     if (_keys.length <= 4 * _size)
141       resize(2 * _keys.length);
142
143     return;
144       }
145       else if (key != testKey && ! testKey.equals(key)) {
146     hash = (hash + 1) & _mask;
147     continue;
148       }
149       else {
150     _values[hash] = value;
151
152     return;
153       }
154     }
155   }
156
157   /**
158    * Puts a new value in the property table with the appropriate flags
159    */

160   public void put(String JavaDoc key, int value)
161   {
162     put(key.toCharArray(), key.length(), value);
163   }
164
165   /**
166    * Expands the property table
167    */

168   private void resize(int newSize)
169   {
170     char [][]newKeys = new char[newSize][];
171     int []newValues = new int[newSize];
172
173     _mask = newKeys.length - 1;
174
175     for (int i = 0; i < _keys.length; i++) {
176       char []key = _keys[i];
177       
178       if (key == null)
179     continue;
180
181       int hash = hash(key, key.length) & _mask;
182
183       while (true) {
184     if (newKeys[hash] == null) {
185       newKeys[hash] = _keys[i];
186       newValues[hash] = _values[i];
187       break;
188     }
189     
190     hash = (hash + 1) & _mask;
191       }
192     }
193
194     _keys = newKeys;
195     _values = newValues;
196   }
197
198   /**
199    * Calculate the hash.
200    */

201   private static int hash(char []key, int length)
202   {
203     int hash = 17;
204
205     for (int i = length - 1; i >= 0; i--) {
206       char a = key[i];
207
208       if ('A' <= a && a <= 'Z')
209     a += 'a' - 'A';
210       
211       hash = 65537 * hash + a;
212     }
213
214     return hash;
215   }
216
217   /**
218    * Calculate equality.
219    */

220   private static boolean equals(char []lower, char []mixed, int length)
221   {
222     if (lower.length != length)
223       return false;
224
225     for (int i = length - 1; i >= 0; i--) {
226       char a = lower[i];
227       char b = mixed[i];
228
229       if ('A' <= b && b <= 'Z')
230     b += 'a' - 'A';
231
232       if (a != b)
233     return false;
234     }
235
236     return true;
237   }
238
239   public String JavaDoc toString()
240   {
241     return "CaseInsensitiveIntMap[]";
242   }
243 }
244
Popular Tags