Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / tools / monkeydoc / Lucene.Net / Lucene.Net / Analysis / CharArraySet.cs
1 /* 
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  * 
9  * http://www.apache.org/licenses/LICENSE-2.0
10  * 
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 using System;
19 namespace Mono.Lucene.Net.Analysis
20 {
21         
22         
23         /// <summary> A simple class that stores Strings as char[]'s in a
24         /// hash table.  Note that this is not a general purpose
25         /// class.  For example, it cannot remove items from the
26         /// set, nor does it resize its hash table to be smaller,
27         /// etc.  It is designed to be quick to test if a char[]
28         /// is in the set without the necessity of converting it
29         /// to a String first.
30         /// </summary>
31         
32         public class CharArraySet:System.Collections.Hashtable
33         {
34                 public override int Count
35                 {
36                         get
37                         {
38                                 return count;
39                         }
40                         
41                 }
42                 private const int INIT_SIZE = 8;
43                 private char[][] entries;
44                 private int count;
45                 private bool ignoreCase;
46                 
47                 /// <summary>Create set with enough capacity to hold startSize
48                 /// terms 
49                 /// </summary>
50                 public CharArraySet(int startSize, bool ignoreCase)
51                 {
52                         this.ignoreCase = ignoreCase;
53                         int size = INIT_SIZE;
54                         while (startSize + (startSize >> 2) > size)
55                                 size <<= 1;
56                         entries = new char[size][];
57                 }
58                 
59                 /// <summary>Create set from a Collection of char[] or String </summary>
60                 public CharArraySet(System.Collections.ICollection c, bool ignoreCase):this(c.Count, ignoreCase)
61                 {
62             System.Collections.IEnumerator e = c is CharArraySet ? ((CharArraySet)c).GetEnumerator() : c.GetEnumerator();
63                         while (e.MoveNext())
64                         {
65                                 Add(e.Current);
66                         }
67                 }
68                 /// <summary>Create set from entries </summary>
69                 private CharArraySet(char[][] entries, bool ignoreCase, int count)
70                 {
71                         this.entries = entries;
72                         this.ignoreCase = ignoreCase;
73                         this.count = count;
74                 }
75                 
76                 /// <summary>true if the <code>len</code> chars of <code>text</code> starting at <code>off</code>
77                 /// are in the set 
78                 /// </summary>
79                 public virtual bool Contains(char[] text, int off, int len)
80                 {
81                         return entries[GetSlot(text, off, len)] != null;
82                 }
83                 
84                 /// <summary>true if the <code>System.String</code> is in the set </summary>
85                 public virtual bool Contains(System.String cs)
86                 {
87                         return entries[GetSlot(cs)] != null;
88                 }
89                 
90                 private int GetSlot(char[] text, int off, int len)
91                 {
92                         int code = GetHashCode(text, off, len);
93                         int pos = code & (entries.Length - 1);
94                         char[] text2 = entries[pos];
95                         if (text2 != null && !Equals(text, off, len, text2))
96                         {
97                                 int inc = ((code >> 8) + code) | 1;
98                                 do 
99                                 {
100                                         code += inc;
101                                         pos = code & (entries.Length - 1);
102                                         text2 = entries[pos];
103                                 }
104                                 while (text2 != null && !Equals(text, off, len, text2));
105                         }
106                         return pos;
107                 }
108                 
109                 /// <summary>Returns true if the String is in the set </summary>
110                 private int GetSlot(System.String text)
111                 {
112                         int code = GetHashCode(text);
113                         int pos = code & (entries.Length - 1);
114                         char[] text2 = entries[pos];
115                         if (text2 != null && !Equals(text, text2))
116                         {
117                                 int inc = ((code >> 8) + code) | 1;
118                                 do 
119                                 {
120                                         code += inc;
121                                         pos = code & (entries.Length - 1);
122                                         text2 = entries[pos];
123                                 }
124                                 while (text2 != null && !Equals(text, text2));
125                         }
126                         return pos;
127                 }
128                 
129                 /// <summary>Add this String into the set </summary>
130                 public virtual bool Add(System.String text)
131                 {
132                         return Add(text.ToCharArray());
133                 }
134                 
135                 /// <summary>Add this char[] directly to the set.
136                 /// If ignoreCase is true for this Set, the text array will be directly modified.
137                 /// The user should never modify this text array after calling this method.
138                 /// </summary>
139                 public virtual bool Add(char[] text)
140                 {
141                         if (ignoreCase)
142                                 for (int i = 0; i < text.Length; i++)
143                                         text[i] = System.Char.ToLower(text[i]);
144                         int slot = GetSlot(text, 0, text.Length);
145                         if (entries[slot] != null)
146                                 return false;
147                         entries[slot] = text;
148                         count++;
149                         
150                         if (count + (count >> 2) > entries.Length)
151                         {
152                                 Rehash();
153                         }
154                         
155                         return true;
156                 }
157                 
158                 private bool Equals(char[] text1, int off, int len, char[] text2)
159                 {
160                         if (len != text2.Length)
161                                 return false;
162                         if (ignoreCase)
163                         {
164                                 for (int i = 0; i < len; i++)
165                                 {
166                                         if (System.Char.ToLower(text1[off + i]) != text2[i])
167                                                 return false;
168                                 }
169                         }
170                         else
171                         {
172                                 for (int i = 0; i < len; i++)
173                                 {
174                                         if (text1[off + i] != text2[i])
175                                                 return false;
176                                 }
177                         }
178                         return true;
179                 }
180                 
181                 private bool Equals(System.String text1, char[] text2)
182                 {
183                         int len = text1.Length;
184                         if (len != text2.Length)
185                                 return false;
186                         if (ignoreCase)
187                         {
188                                 for (int i = 0; i < len; i++)
189                                 {
190                                         if (System.Char.ToLower(text1[i]) != text2[i])
191                                                 return false;
192                                 }
193                         }
194                         else
195                         {
196                                 for (int i = 0; i < len; i++)
197                                 {
198                                         if (text1[i] != text2[i])
199                                                 return false;
200                                 }
201                         }
202                         return true;
203                 }
204                 
205                 private void  Rehash()
206                 {
207                         int newSize = 2 * entries.Length;
208                         char[][] oldEntries = entries;
209                         entries = new char[newSize][];
210                         
211                         for (int i = 0; i < oldEntries.Length; i++)
212                         {
213                                 char[] text = oldEntries[i];
214                                 if (text != null)
215                                 {
216                                         // todo: could be faster... no need to compare strings on collision
217                                         entries[GetSlot(text, 0, text.Length)] = text;
218                                 }
219                         }
220                 }
221
222         private int GetHashCode(char[] text, int offset, int len)
223                 {
224                         int code = 0;
225                         int stop = offset + len;
226                         if (ignoreCase)
227                         {
228                                 for (int i = offset; i < stop; i++)
229                                 {
230                                         code = code * 31 + System.Char.ToLower(text[i]);
231                                 }
232                         }
233                         else
234                         {
235                                 for (int i = offset; i < stop; i++)
236                                 {
237                                         code = code * 31 + text[i];
238                                 }
239                         }
240                         return code;
241                 }
242                 
243                 private int GetHashCode(System.String text)
244                 {
245                         int code = 0;
246                         int len = text.Length;
247                         if (ignoreCase)
248                         {
249                                 for (int i = 0; i < len; i++)
250                                 {
251                                         code = code * 31 + System.Char.ToLower(text[i]);
252                                 }
253                         }
254                         else
255                         {
256                                 for (int i = 0; i < len; i++)
257                                 {
258                                         code = code * 31 + text[i];
259                                 }
260                         }
261                         return code;
262                 }
263                 
264                 public virtual int Size()
265                 {
266                         return count;
267                 }
268                 
269                 public virtual bool IsEmpty()
270                 {
271                         return count == 0;
272                 }
273                 
274                 public override bool Contains(System.Object o)
275                 {
276                         if (o is char[])
277                         {
278                                 char[] text = (char[]) o;
279                                 return Contains(text, 0, text.Length);
280                         }
281                         return Contains(o.ToString());
282                 }
283
284         //LUCENENET-414 (https://issues.apache.org/jira/browse/LUCENENET-414)
285         public virtual bool Add(object key, object value)
286         {
287             return Add(key);
288         }
289
290                 public virtual bool Add(System.Object o)
291                 {
292                         if (o is char[])
293                         {
294                                 return Add((char[]) o);
295                         }
296
297             if (o is System.Collections.Hashtable)
298             {
299                 foreach (string word in ((System.Collections.Hashtable)o).Keys)
300                 {
301                     Add(word);
302                 }
303                 return true;
304             }
305
306                         return Add(o.ToString());
307                 }
308                 
309                 /// <summary> Returns an unmodifiable {@link CharArraySet}. This allows to provide
310                 /// unmodifiable views of internal sets for "read-only" use.
311                 /// 
312                 /// </summary>
313                 /// <param name="set">a set for which the unmodifiable set is returned.
314                 /// </param>
315                 /// <returns> an new unmodifiable {@link CharArraySet}.
316                 /// </returns>
317                 /// <throws>  NullPointerException </throws>
318                 /// <summary>           if the given set is <code>null</code>.
319                 /// </summary>
320                 public static CharArraySet UnmodifiableSet(CharArraySet set_Renamed)
321                 {
322                         if (set_Renamed == null)
323                                 throw new System.NullReferenceException("Given set is null");
324                         /*
325                         * Instead of delegating calls to the given set copy the low-level values to
326                         * the unmodifiable Subclass
327                         */
328                         return new UnmodifiableCharArraySet(set_Renamed.entries, set_Renamed.ignoreCase, set_Renamed.count);
329                 }
330
331         /// <summary>The Iterator&lt;String&gt; for this set.  Strings are constructed on the fly, so
332                 /// use <code>nextCharArray</code> for more efficient access. 
333                 /// </summary>
334                 public class CharArraySetIterator : System.Collections.IEnumerator
335                 {
336                         private void  InitBlock(CharArraySet enclosingInstance)
337                         {
338                                 this.enclosingInstance = enclosingInstance;
339                         }
340                         private CharArraySet enclosingInstance;
341             /// <summary>Returns the next String, as a Set&lt;String&gt; would...
342                         /// use nextCharArray() for better efficiency. 
343                         /// </summary>
344                         public virtual System.Object Current
345                         {
346                                 get
347                                 {
348                                         return new System.String(NextCharArray());
349                                 }
350                                 
351                         }
352                         public CharArraySet Enclosing_Instance
353                         {
354                                 get
355                                 {
356                                         return enclosingInstance;
357                                 }
358                                 
359                         }
360                         internal int pos = - 1;
361                         internal char[] next_Renamed_Field;
362                         internal CharArraySetIterator(CharArraySet enclosingInstance)
363                         {
364                                 InitBlock(enclosingInstance);
365                                 GoNext();
366                         }
367                         
368                         private void  GoNext()
369                         {
370                                 next_Renamed_Field = null;
371                                 pos++;
372                                 while (pos < Enclosing_Instance.entries.Length && (next_Renamed_Field = Enclosing_Instance.entries[pos]) == null)
373                                         pos++;
374                         }
375                         
376                         public virtual bool MoveNext()
377                         {
378                                 return next_Renamed_Field != null;
379                         }
380                         
381                         /// <summary>do not modify the returned char[] </summary>
382                         public virtual char[] NextCharArray()
383                         {
384                                 char[] ret = next_Renamed_Field;
385                                 GoNext();
386                                 return ret;
387                         }
388                         
389                         public virtual void  Remove()
390                         {
391                                 throw new System.NotSupportedException();
392                         }
393                         
394                         virtual public void  Reset()
395                         {
396                 System.Diagnostics.Debug.Fail("Port issue:", "Need to implement this call, CharArraySetIterator.Reset()");  // {{Aroush-2.9
397                         }
398                 }
399                 
400                 
401                 public new System.Collections.IEnumerator GetEnumerator()
402                 {
403                         return new CharArraySetIterator(this);
404                 }
405                 
406                 /// <summary> Efficient unmodifiable {@link CharArraySet}. This implementation does not
407                 /// delegate calls to a give {@link CharArraySet} like
408                 /// {@link Collections#UnmodifiableSet(java.util.Set)} does. Instead is passes
409                 /// the internal representation of a {@link CharArraySet} to a super
410                 /// constructor and overrides all mutators. 
411                 /// </summary>
412                 private sealed class UnmodifiableCharArraySet:CharArraySet
413                 {
414                         
415                         internal UnmodifiableCharArraySet(char[][] entries, bool ignoreCase, int count):base(entries, ignoreCase, count)
416                         {
417                         }
418                         
419                         public override bool Add(System.Object o)
420                         {
421                                 throw new System.NotSupportedException();
422                         }
423                         
424                         public override bool AddAll(System.Collections.ICollection coll)
425                         {
426                                 throw new System.NotSupportedException();
427                         }
428                         
429                         public override bool Add(char[] text)
430                         {
431                                 throw new System.NotSupportedException();
432                         }
433                         
434                         public override bool Add(System.String text)
435                         {
436                                 throw new System.NotSupportedException();
437                         }
438                 }
439
440         /// <summary>Adds all of the elements in the specified collection to this collection </summary>
441         public virtual bool AddAll(System.Collections.ICollection items)
442         {
443             bool added = false;
444             System.Collections.IEnumerator iter = items.GetEnumerator();
445             System.Object item;
446             while (iter.MoveNext())
447             {
448                 item = iter.Current;
449                 added = Add(item);
450             }
451             return added;
452         }
453
454         /// <summary>Removes all elements from the set </summary>
455         public virtual new bool Clear()
456         {
457             throw new System.NotSupportedException();
458         }
459
460         /// <summary>Removes from this set all of its elements that are contained in the specified collection </summary>
461         public virtual bool RemoveAll(System.Collections.ICollection items)
462         {
463             throw new System.NotSupportedException();
464         }
465
466         /// <summary>Retains only the elements in this set that are contained in the specified collection </summary>
467         public bool RetainAll(System.Collections.ICollection coll)
468         {
469             throw new System.NotSupportedException();
470         }
471     }
472 }