You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by sy...@apache.org on 2016/05/12 20:57:10 UTC
[3/3] lucenenet git commit: WIP
WIP
Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/447e2ce1
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/447e2ce1
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/447e2ce1
Branch: refs/heads/analysis-work
Commit: 447e2ce16d7d6d6b6659704eb09bb18814474668
Parents: 6533b77
Author: Itamar Syn-Hershko <it...@code972.com>
Authored: Thu May 12 23:56:38 2016 +0300
Committer: Itamar Syn-Hershko <it...@code972.com>
Committed: Thu May 12 23:56:38 2016 +0300
----------------------------------------------------------------------
.../Analysis/Core/UpperCaseFilter.cs | 2 +-
.../Miscellaneous/ASCIIFoldingFilter.cs | 2 +-
.../Miscellaneous/PerFieldAnalyzerWrapper.cs | 2 +-
.../Analysis/Util/AbstractAnalysisFactory.cs | 93 +-
.../Analysis/Util/CharArrayMap.cs | 1981 ++++++++++--------
.../Analysis/Util/CharArraySet.cs | 426 ++--
.../Analysis/Util/RollingCharBuffer.cs | 4 +-
.../Lucene.Net.Analysis.Common.csproj | 3 +
.../Support/Compatibility/Collections.cs | 5 +
src/Lucene.Net.Core/Support/SetExtensions.cs | 3 +
.../JavaCompatibility/LuceneTestCase.cs | 13 +-
.../JavaCompatibility/LuceneTypesHelpers.cs | 2 +-
.../JavaCompatibility/SystemTypesHelpers.cs | 49 +-
.../Analysis/Util/TestCharArrayMap.cs | 515 ++---
.../Analysis/Util/TestCharArraySet.cs | 1148 +++++-----
.../Analysis/Util/TestCharTokenizers.cs | 1 +
.../Lucene.Net.Tests.Analysis.Common.csproj | 2 +
17 files changed, 2253 insertions(+), 1998 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/447e2ce1/src/Lucene.Net.Analysis.Common/Analysis/Core/UpperCaseFilter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Core/UpperCaseFilter.cs b/src/Lucene.Net.Analysis.Common/Analysis/Core/UpperCaseFilter.cs
index c8b5f5f..d97109d 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Core/UpperCaseFilter.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Core/UpperCaseFilter.cs
@@ -29,7 +29,7 @@ namespace Lucene.Net.Analysis.Core
/// </para>
/// <para><b>NOTE:</b> In Unicode, this transformation may lose information when the
/// upper case character represents more than one lower case character. Use this filter
- /// when you require uppercase tokens. Use the <seealso cref="LowerCaseFilter"/> for
+ /// when you Require uppercase tokens. Use the <seealso cref="LowerCaseFilter"/> for
/// general search matching
/// </para>
/// </summary>
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/447e2ce1/src/Lucene.Net.Analysis.Common/Analysis/Miscellaneous/ASCIIFoldingFilter.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Miscellaneous/ASCIIFoldingFilter.cs b/src/Lucene.Net.Analysis.Common/Analysis/Miscellaneous/ASCIIFoldingFilter.cs
index 18df853..318a7df 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Miscellaneous/ASCIIFoldingFilter.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Miscellaneous/ASCIIFoldingFilter.cs
@@ -109,7 +109,7 @@ namespace Lucene.Net.Analysis.Miscellaneous
char[] buffer = termAtt.Buffer();
int length = termAtt.Length;
- // If no characters actually require rewriting then we
+ // If no characters actually Require rewriting then we
// just return token as-is:
for (int i = 0; i < length; ++i)
{
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/447e2ce1/src/Lucene.Net.Analysis.Common/Analysis/Miscellaneous/PerFieldAnalyzerWrapper.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Miscellaneous/PerFieldAnalyzerWrapper.cs b/src/Lucene.Net.Analysis.Common/Analysis/Miscellaneous/PerFieldAnalyzerWrapper.cs
index d43a407..65b43fb 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Miscellaneous/PerFieldAnalyzerWrapper.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Miscellaneous/PerFieldAnalyzerWrapper.cs
@@ -24,7 +24,7 @@ namespace Lucene.Net.Analysis.Miscellaneous
/// <summary>
/// This analyzer is used to facilitate scenarios where different
- /// fields require different analysis techniques. Use the Map
+ /// fields Require different analysis techniques. Use the Map
/// argument in <seealso cref="#PerFieldAnalyzerWrapper(Analyzer, java.util.Map)"/>
/// to add non-default analyzers for fields.
///
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/447e2ce1/src/Lucene.Net.Analysis.Common/Analysis/Util/AbstractAnalysisFactory.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Util/AbstractAnalysisFactory.cs b/src/Lucene.Net.Analysis.Common/Analysis/Util/AbstractAnalysisFactory.cs
index b62a110..a677380 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Util/AbstractAnalysisFactory.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Util/AbstractAnalysisFactory.cs
@@ -32,9 +32,9 @@ namespace Lucene.Net.Analysis.Util
/// <para>
/// The typical lifecycle for a factory consumer is:
/// <ol>
- /// <li>Create factory via its constructor (or via XXXFactory.forName)
- /// <li>(Optional) If the factory uses resources such as files, <seealso cref="ResourceLoaderAware#inform(ResourceLoader)"/> is called to initialize those resources.
- /// <li>Consumer calls create() to obtain instances.
+ /// <li>Create factory via its constructor (or via XXXFactory.forName)</li>
+ /// <li>(Optional) If the factory uses resources such as files, <seealso cref="ResourceLoaderAware#inform(ResourceLoader)"/> is called to initialize those resources.</li>
+ /// <li>Consumer calls create() to obtain instances.</li>
/// </ol>
/// </para>
/// </summary>
@@ -48,7 +48,7 @@ namespace Lucene.Net.Analysis.Util
/// <summary>
/// the luceneVersion arg </summary>
- protected internal readonly LuceneVersion? luceneMatchVersion;
+ protected internal readonly Version? luceneMatchVersion;
/// <summary>
/// Initialize this factory via a set of key-value pairs.
@@ -57,7 +57,7 @@ namespace Lucene.Net.Analysis.Util
{
ExplicitLuceneMatchVersion = false;
originalArgs = Collections.UnmodifiableMap(args);
- string version = get(args, LUCENE_MATCH_VERSION_PARAM);
+ string version = Get(args, LUCENE_MATCH_VERSION_PARAM);
luceneMatchVersion = version == null ? (LuceneVersion?)null : LuceneVersionHelpers.ParseLeniently(version);
args.Remove(CLASS_NAME); // consume the class arg
}
@@ -91,7 +91,7 @@ namespace Lucene.Net.Analysis.Util
}
}
- public virtual string require(IDictionary<string, string> args, string name)
+ public virtual string Require(IDictionary<string, string> args, string name)
{
string s;
if (!args.TryGetValue(name, out s))
@@ -101,55 +101,58 @@ namespace Lucene.Net.Analysis.Util
args.Remove(name);
return s;
}
- public virtual string require(IDictionary<string, string> args, string name, ICollection<string> allowedValues)
+ public virtual string Require(IDictionary<string, string> args, string name, ICollection<string> allowedValues)
{
- return require(args, name, allowedValues, true);
+ return Require(args, name, allowedValues, true);
}
- public virtual string require(IDictionary<string, string> args, string name, ICollection<string> allowedValues, bool caseSensitive)
+
+ public virtual string Require(IDictionary<string, string> args, string name, ICollection<string> allowedValues,
+ bool caseSensitive)
{
- string s = args.Remove(name);
- if (s == null)
+ string s;
+ if (!args.TryGetValue(name, out s) || s == null)
{
- throw new System.ArgumentException("Configuration Error: missing parameter '" + name + "'");
+ throw new ArgumentException("Configuration Error: missing parameter '" + name + "'");
}
- else
+
+ args.Remove(name);
+ foreach (var allowedValue in allowedValues)
{
- foreach (string allowedValue in allowedValues)
+ if (caseSensitive)
{
- if (caseSensitive)
+ if (s.Equals(allowedValue))
{
- if (s.Equals(allowedValue))
- {
- return s;
- }
+ return s;
}
- else
+ }
+ else
+ {
+ if (s.Equals(allowedValue, StringComparison.CurrentCultureIgnoreCase))
{
- if (s.Equals(allowedValue, StringComparison.CurrentCultureIgnoreCase))
- {
- return s;
- }
+ return s;
}
}
- throw new System.ArgumentException("Configuration Error: '" + name + "' value must be one of " + allowedValues);
}
+ throw new ArgumentException("Configuration Error: '" + name + "' value must be one of " +
+ allowedValues);
}
- public virtual string get(IDictionary<string, string> args, string name, string defaultVal = null)
+
+ public virtual string Get(IDictionary<string, string> args, string name, string defaultVal = null)
{
string s;
if (args.TryGetValue(name, out s))
args.Remove(name);
return s ?? defaultVal;
}
- public virtual string get(IDictionary<string, string> args, string name, ICollection<string> allowedValues)
+ public virtual string Get(IDictionary<string, string> args, string name, ICollection<string> allowedValues)
{
- return get(args, name, allowedValues, null); // defaultVal = null
+ return Get(args, name, allowedValues, null); // defaultVal = null
}
- public virtual string get(IDictionary<string, string> args, string name, ICollection<string> allowedValues, string defaultVal)
+ public virtual string Get(IDictionary<string, string> args, string name, ICollection<string> allowedValues, string defaultVal)
{
- return get(args, name, allowedValues, defaultVal, true);
+ return Get(args, name, allowedValues, defaultVal, true);
}
- public virtual string get(IDictionary<string, string> args, string name, ICollection<string> allowedValues, string defaultVal, bool caseSensitive)
+ public virtual string Get(IDictionary<string, string> args, string name, ICollection<string> allowedValues, string defaultVal, bool caseSensitive)
{
string s = null;
if (args.TryGetValue(name, out s))
@@ -181,41 +184,41 @@ namespace Lucene.Net.Analysis.Util
}
}
- protected internal int requireInt(IDictionary<string, string> args, string name)
+ protected internal int RequireInt(IDictionary<string, string> args, string name)
{
- return int.Parse(require(args, name));
+ return int.Parse(Require(args, name));
}
- protected internal int getInt(IDictionary<string, string> args, string name, int defaultVal)
+ protected internal int GetInt(IDictionary<string, string> args, string name, int defaultVal)
{
string s = args.Remove(name);
return s == null ? defaultVal : int.Parse(s);
}
- protected internal bool requireBoolean(IDictionary<string, string> args, string name)
+ protected internal bool RequireBoolean(IDictionary<string, string> args, string name)
{
- return bool.Parse(require(args, name));
+ return bool.Parse(Require(args, name));
}
- protected internal bool getBoolean(IDictionary<string, string> args, string name, bool defaultVal)
+ protected internal bool GetBoolean(IDictionary<string, string> args, string name, bool defaultVal)
{
string s = args.Remove(name);
return s == null ? defaultVal : bool.Parse(s);
}
- protected internal float requireFloat(IDictionary<string, string> args, string name)
+ protected internal float RequireFloat(IDictionary<string, string> args, string name)
{
- return float.Parse(require(args, name));
+ return float.Parse(Require(args, name));
}
- protected internal float getFloat(IDictionary<string, string> args, string name, float defaultVal)
+ protected internal float GetFloat(IDictionary<string, string> args, string name, float defaultVal)
{
string s = args.Remove(name);
return s == null ? defaultVal : float.Parse(s);
}
- public virtual char requireChar(IDictionary<string, string> args, string name)
+ public virtual char RequireChar(IDictionary<string, string> args, string name)
{
- return require(args, name)[0];
+ return Require(args, name)[0];
}
- public virtual char getChar(IDictionary<string, string> args, string name, char defaultValue)
+ public virtual char GetChar(IDictionary<string, string> args, string name, char defaultValue)
{
string s = args.Remove(name);
if (s == null)
@@ -239,7 +242,7 @@ namespace Lucene.Net.Analysis.Util
/// <summary>
/// Returns whitespace- and/or comma-separated set of values, or null if none are found </summary>
- public virtual HashSet<string> getSet(IDictionary<string, string> args, string name)
+ public virtual HashSet<string> GetSet(IDictionary<string, string> args, string name)
{
string s = args.Remove(name);
if (s == null)
@@ -270,7 +273,7 @@ namespace Lucene.Net.Analysis.Util
{
try
{
- return Pattern.compile(require(args, name));
+ return Pattern.compile(Require(args, name));
}
catch (PatternSyntaxException e)
{
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/447e2ce1/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs b/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs
index 78aacd7..d7fc4ab 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs
@@ -9,7 +9,7 @@ using Lucene.Net.Util;
namespace Lucene.Net.Analysis.Util
{
- /*
+ /*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
@@ -27,912 +27,1075 @@ namespace Lucene.Net.Analysis.Util
*/
- /// <summary>
- /// A simple class that stores key Strings as char[]'s in a
- /// hash table. Note that this is not a general purpose
- /// class. For example, it cannot remove items from the
- /// map, nor does it resize its hash table to be smaller,
- /// etc. It is designed to be quick to retrieve items
- /// by char[] keys without the necessity of converting
- /// to a String first.
- ///
- /// <a name="version"></a>
- /// <para>You must specify the required <seealso cref="Version"/>
- /// compatibility when creating <seealso cref="CharArrayMap"/>:
- /// <ul>
- /// <li> As of 3.1, supplementary characters are
- /// properly lowercased.</li>
- /// </ul>
- /// Before 3.1 supplementary characters could not be
- /// lowercased correctly due to the lack of Unicode 4
- /// support in JDK 1.4. To use instances of
- /// <seealso cref="CharArrayMap"/> with the behavior before Lucene
- /// 3.1 pass a <seealso cref="Version"/> < 3.1 to the constructors.
- /// </para>
- /// </summary>
- public class CharArrayMap<V> : IDictionary<object, V>
- {
- // private only because missing generics
- private static readonly CharArrayMap<char[]> EMPTY_MAP = new EmptyCharArrayMap<char[]>();
-
- private const int INIT_SIZE = 8;
- private readonly CharacterUtils charUtils;
- private bool ignoreCase;
- private int count;
- internal readonly LuceneVersion matchVersion; // package private because used in CharArraySet
- internal char[][] keys; // package private because used in CharArraySet's non Set-conform CharArraySetIterator
- internal V[] values; // package private because used in CharArraySet's non Set-conform CharArraySetIterator
-
- /// <summary>
- /// Create map with enough capacity to hold startSize terms
- /// </summary>
- /// <param name="matchVersion">
- /// compatibility match version see <a href="#version">Version
- /// note</a> above for details. </param>
- /// <param name="startSize">
- /// the initial capacity </param>
- /// <param name="ignoreCase">
- /// <code>false</code> if and only if the set should be case sensitive
- /// otherwise <code>true</code>. </param>
- public CharArrayMap(LuceneVersion matchVersion, int startSize, bool ignoreCase)
- {
- this.ignoreCase = ignoreCase;
- int size = INIT_SIZE;
- while (startSize + (startSize >> 2) > size)
- {
- size <<= 1;
- }
- keys = new char[size][];
- values = new V[size];
- this.charUtils = CharacterUtils.GetInstance(matchVersion);
- this.matchVersion = matchVersion;
- }
-
- /// <summary>
- /// Creates a map from the mappings in another map.
- /// </summary>
- /// <param name="matchVersion">
- /// compatibility match version see <a href="#version">Version
- /// note</a> above for details. </param>
- /// <param name="c">
- /// a map whose mappings to be copied </param>
- /// <param name="ignoreCase">
- /// <code>false</code> if and only if the set should be case sensitive
- /// otherwise <code>true</code>. </param>
- public CharArrayMap(LuceneVersion matchVersion, IDictionary<object, V> c, bool ignoreCase)
- : this(matchVersion, c.Count, ignoreCase)
- {
- foreach (var v in c)
- {
- Add(v);
- }
- }
-
- /// <summary>
- /// Create set from the supplied map (used internally for readonly maps...) </summary>
- private CharArrayMap(CharArrayMap<V> toCopy)
- {
- this.keys = toCopy.keys;
- this.values = toCopy.values;
- this.ignoreCase = toCopy.ignoreCase;
- this.count = toCopy.count;
- this.charUtils = toCopy.charUtils;
- this.matchVersion = toCopy.matchVersion;
- }
-
- public void Add(KeyValuePair<object, V> item)
- {
- Put(item.Key, item.Value);
- }
-
- /// <summary>
- /// Clears all entries in this map. This method is supported for reusing, but not <seealso cref="Map#remove"/>. </summary>
- public virtual void Clear()
- {
- count = 0;
- Arrays.Fill(keys, null);
- Arrays.Fill(values, default(V));
- }
-
- public bool Contains(KeyValuePair<object, V> item)
- {
- throw new NotImplementedException();
- }
-
- /// <summary>
- /// true if the <code>len</code> chars of <code>text</code> starting at <code>off</code>
- /// are in the <seealso cref="#keySet()"/>
- /// </summary>
- public virtual bool ContainsKey(char[] text, int off, int len)
- {
- return keys[GetSlot(text, off, len)] != null;
- }
-
- /// <summary>
- /// true if the <code>CharSequence</code> is in the <seealso cref="#keySet()"/> </summary>
- public virtual bool ContainsKey(string cs)
- {
- return keys[GetSlot(cs)] != null;
- }
-
- public virtual bool ContainsKey(object o)
- {
- var c = o as char[];
- if (c != null)
- {
- var text = c;
- return ContainsKey(text, 0, text.Length);
- }
- return ContainsKey(o.ToString());
- }
-
- public void Add(object key, V value)
- {
- Put(key, value);
- }
-
- /// <summary>
- /// returns the value of the mapping of <code>len</code> chars of <code>text</code>
- /// starting at <code>off</code>
- /// </summary>
- public virtual V Get(char[] text, int off, int len)
- {
- return values[GetSlot(text, off, len)];
- }
-
- /// <summary>
- /// returns the value of the mapping of the chars inside this {@code CharSequence} </summary>
- public virtual V Get(string cs)
- {
- return values[GetSlot(cs)];
- }
-
- public virtual V Get(object o)
- {
- var text = o as char[];
- if (text != null)
- {
- return Get(text, 0, text.Length);
- }
- return Get(o.ToString());
- }
-
- private int GetSlot(char[] text, int off, int len)
- {
- int code = getHashCode(text, off, len);
- int pos = code & (keys.Length - 1);
- char[] text2 = keys[pos];
- if (text2 != null && !Equals(text, off, len, text2))
- {
- int inc = ((code >> 8) + code) | 1;
- do
- {
- code += inc;
- pos = code & (keys.Length - 1);
- text2 = keys[pos];
- } while (text2 != null && !Equals(text, off, len, text2));
- }
- return pos;
- }
-
- /// <summary>
- /// Returns true if the String is in the set </summary>
- private int GetSlot(string text)
- {
- int code = getHashCode(text);
- int pos = code & (keys.Length - 1);
- char[] text2 = keys[pos];
- if (text2 != null && !Equals(text, text2))
- {
- int inc = ((code >> 8) + code) | 1;
- do
- {
- code += inc;
- pos = code & (keys.Length - 1);
- text2 = keys[pos];
- } while (text2 != null && !Equals(text, text2));
- }
- return pos;
- }
-
- /// <summary>
- /// Add the given mapping. </summary>
- public virtual V Put(ICharSequence text, V value)
- {
- return Put(text.ToString(), value); // could be more efficient
- }
-
- public virtual V Put(object o, V value)
- {
- var c = o as char[];
- if (c != null)
- {
- return Put(c, value);
- }
- return Put(o.ToString(), value);
- }
-
- /// <summary>
- /// Add the given mapping. </summary>
- public virtual V Put(string text, V value)
- {
- return Put(text.ToCharArray(), value);
- }
-
- /// <summary>
- /// Add the given mapping.
- /// If ignoreCase is true for this Set, the text array will be directly modified.
- /// The user should never modify this text array after calling this method.
- /// </summary>
- public virtual V Put(char[] text, V value)
- {
- if (ignoreCase)
- {
- charUtils.ToLower(text, 0, text.Length);
- }
- int slot = GetSlot(text, 0, text.Length);
- if (keys[slot] != null)
- {
- V oldValue = values[slot];
- values[slot] = value;
- return oldValue;
- }
- keys[slot] = text;
- values[slot] = value;
- count++;
-
- if (count + (count >> 2) > keys.Length)
- {
- Rehash();
- }
-
- return default(V);
- }
-
- private void Rehash()
- {
- Debug.Assert(keys.Length == values.Length);
- int newSize = 2 * keys.Length;
- char[][] oldkeys = keys;
- V[] oldvalues = values;
- keys = new char[newSize][];
- values = new V[newSize];
-
- for (int i = 0; i < oldkeys.Length; i++)
- {
- char[] text = oldkeys[i];
- if (text != null)
- {
- // todo: could be faster... no need to compare strings on collision
- int slot = GetSlot(text,0,text.Length);
- keys[slot] = text;
- values[slot] = oldvalues[i];
- }
- }
- }
-
- private bool Equals(char[] text1, int off, int len, char[] text2)
- {
- if (len != text2.Length)
- {
- return false;
- }
- int limit = off + len;
- if (ignoreCase)
- {
- for (int i = 0;i < len;)
- {
- var codePointAt = charUtils.CodePointAt(text1, off + i, limit);
- if (char.ToLower((char)codePointAt) != charUtils.CodePointAt(text2, i, text2.Length))
- {
- return false;
- }
- i += Character.CharCount(codePointAt);
- }
- }
- else
- {
- for (int i = 0;i < len;i++)
- {
- if (text1[off + i] != text2[i])
- {
- return false;
- }
- }
- }
- return true;
- }
-
- private bool Equals(ICharSequence text1, char[] text2)
- {
- int len = text1.Length;
- if (len != text2.Length)
- {
- return false;
- }
- if (ignoreCase)
- {
- for (int i = 0;i < len;)
- {
- int codePointAt = charUtils.CodePointAt(text1, i);
- if (char.ToLower((char)codePointAt) != charUtils.CodePointAt(text2, i, text2.Length))
- {
- return false;
- }
- i += Character.CharCount(codePointAt);
- }
- }
- else
- {
- for (int i = 0;i < len;i++)
- {
- if (text1.CharAt(i) != text2[i])
- {
- return false;
- }
- }
- }
- return true;
- }
-
- private int getHashCode(char[] text, int offset, int len)
- {
- if (text == null)
- {
- throw new ArgumentException("text can't be null", "text");
- }
- int code = 0;
- int stop = offset + len;
- if (ignoreCase)
- {
- for (int i = offset; i < stop;)
- {
- int codePointAt = charUtils.CodePointAt(text, i, stop);
- code = code * 31 + char.ToLower((char)codePointAt);
- i += Character.CharCount(codePointAt);
- }
- }
- else
- {
- for (int i = offset; i < stop; i++)
- {
- code = code * 31 + text[i];
- }
- }
- return code;
- }
-
- private int getHashCode(string text)
- {
- if (text == null)
- {
- throw new ArgumentException("text can't be null", "text");
- }
- int code = 0;
- int len = text.Length;
- if (ignoreCase)
- {
- for (int i = 0; i < len;)
- {
- int codePointAt = charUtils.CodePointAt(text, i);
- code = code * 31 + char.ToLower((char)codePointAt);
- i += Character.CharCount(codePointAt);
- }
- }
- else
- {
- for (int i = 0; i < len; i++)
- {
- code = code * 31 + text[i];
- }
- }
- return code;
- }
-
- public virtual bool Remove(object key)
- {
- throw new System.NotSupportedException();
- }
-
- public bool TryGetValue(object key, out V value)
- {
- throw new NotImplementedException();
- }
-
- public V this[object key]
- {
- get { return Get(key); }
- set { throw new NotSupportedException(); }
- }
-
- public bool Remove(KeyValuePair<object, V> item)
- {
- throw new System.NotSupportedException();
- }
-
- public int Count
- {
- get
- {
- {
- return count;
- }
- }
- }
-
- public bool IsReadOnly { get; private set; }
-
- public override string ToString()
- {
- var sb = new StringBuilder("{");
- foreach (KeyValuePair<object, V> entry in GetEntrySet())
- {
- if (sb.Length > 1)
- {
- sb.Append(", ");
- }
- sb.Append(entry);
- }
- return sb.Append('}').ToString();
- }
-
- private EntrySet entrySet_Renamed = null;
- private CharArraySet keySet_Renamed = null;
-
- internal virtual EntrySet CreateEntrySet()
- {
- return new EntrySet(this, true);
- }
-
- public EntrySet GetEntrySet()
- {
- if (entrySet_Renamed == null)
- {
- entrySet_Renamed = CreateEntrySet();
- }
- return entrySet_Renamed;
- }
-
- // helper for CharArraySet to not produce endless recursion
- internal HashSet<object> originalKeySet()
- {
- return base.Keys;
- }
-
- /// <summary>
- /// Returns an <seealso cref="CharArraySet"/> view on the map's keys.
- /// The set will use the same {@code matchVersion} as this map.
- /// </summary>
- public CharArraySet KeySet()
- {
- if (keySet_Renamed == null)
- {
- // prevent adding of entries
- keySet_Renamed = new CharArraySetAnonymousInnerClassHelper(this);
- }
- return keySet_Renamed;
- }
-
- private sealed class CharArraySetAnonymousInnerClassHelper : CharArraySet
- {
- internal CharArraySetAnonymousInnerClassHelper(CharArrayMap<object> map) : base(map)
- {
- // TODO
- }
-
- public override bool Add(object o)
- {
- throw new System.NotSupportedException();
- }
- public bool Add(ICharSequence text)
- {
- throw new System.NotSupportedException();
- }
- public override bool Add(string text)
- {
- throw new System.NotSupportedException();
- }
- public override bool Add(char[] text)
- {
- throw new System.NotSupportedException();
- }
- }
-
- /// <summary>
- /// public iterator class so efficient methods are exposed to users
- /// </summary>
- public class EntryIterator : IEnumerator<KeyValuePair<object, V>>
- {
- private readonly CharArrayMap<V> outerInstance;
-
- internal int pos = -1;
- internal int lastPos;
- internal readonly bool allowModify;
-
- internal EntryIterator(CharArrayMap<V> outerInstance, bool allowModify)
- {
- this.outerInstance = outerInstance;
- this.allowModify = allowModify;
- GoNext();
- }
-
- internal void GoNext()
- {
- lastPos = pos;
- pos++;
- while (pos < outerInstance.keys.Length && outerInstance.keys[pos] == null)
- {
- pos++;
- }
- }
-
- public bool HasNext()
- {
- return pos < outerInstance.keys.Length;
- }
-
- /// <summary>
- /// gets the next key... do not modify the returned char[] </summary>
- public virtual char[] NextKey()
- {
- GoNext();
- return outerInstance.keys[lastPos];
- }
-
- /// <summary>
- /// gets the next key as a newly created String object </summary>
- public virtual string NextKeyString()
- {
- return new string(NextKey());
- }
-
- /// <summary>
- /// returns the value associated with the last key returned </summary>
- public virtual V CurrentValue()
- {
- return outerInstance.values[lastPos];
- }
-
- /// <summary>
- /// sets the value associated with the last key returned </summary>
- public virtual V SetValue(V value)
- {
- if (!allowModify)
- {
- throw new System.NotSupportedException();
- }
- V old = outerInstance.values[lastPos];
- outerInstance.values[lastPos] = value;
- return old;
- }
-
- /// <summary>
- /// use nextCharArray() + currentValue() for better efficiency.
- /// </summary>
- public KeyValuePair<object, V> Next()
- {
- GoNext();
- //return new KeyValuePair<object, V>();
- return new MapEntry(outerInstance, lastPos, allowModify);
- }
-
- public void Remove()
- {
- throw new System.NotSupportedException();
- }
-
- #region Added for better .NET support
- public void Dispose()
- {
- }
-
- public bool MoveNext()
- {
- if (!HasNext()) return false;
- GoNext();
- return true;
- }
-
- public void Reset()
- {
- pos = -1;
- GoNext();
- }
-
- public KeyValuePair<object, V> Current { get { return new KeyValuePair<object, V>(outerInstance.keys[lastPos], outerInstance.values[lastPos]); } private set { } }
-
- object IEnumerator.Current
- {
- get { return CurrentValue(); }
- }
- #endregion
- }
-
- private sealed class MapEntry : KeyValuePair<object, V>
- {
- private readonly CharArrayMap<V> outerInstance;
-
- internal readonly int pos;
- internal readonly bool allowModify;
-
- internal MapEntry(CharArrayMap<V> outerInstance, int pos, bool allowModify)
- {
- this.outerInstance = outerInstance;
- this.pos = pos;
- this.allowModify = allowModify;
- }
-
- public object Key
- {
- get
- {
- // we must clone here, as putAll to another CharArrayMap
- // with other case sensitivity flag would corrupt the keys
- return outerInstance.keys[pos].Clone();
- }
- }
-
- public V Value
- {
- get
- {
- return outerInstance.values[pos];
- }
- }
-
- public V setValue(V value)
- {
- if (!allowModify)
- {
- throw new System.NotSupportedException();
- }
- V old = outerInstance.values[pos];
- outerInstance.values[pos] = value;
- return old;
- }
-
- public override string ToString()
- {
- return (new StringBuilder())
- .Append(outerInstance.keys[pos])
- .Append('=')
- .Append((outerInstance.values[pos] == outerInstance) ? "(this Map)" : outerInstance.values[pos]).ToString();
- }
- }
-
- /// <summary>
- /// public EntrySet class so efficient methods are exposed to users </summary>
- public sealed class EntrySet : ISet<KeyValuePair<object, V>>
- {
- private readonly CharArrayMap<V> outerInstance;
-
- internal readonly bool allowModify;
-
- internal EntrySet(CharArrayMap<V> outerInstance, bool allowModify)
- {
- this.outerInstance = outerInstance;
- this.allowModify = allowModify;
- }
-
- public IEnumerator GetEnumerator()
- {
- return new EntryIterator(outerInstance, allowModify);
- }
-
- public override bool Contains(object o)
- {
- if (!(o is DictionaryEntry))
- {
- return false;
- }
- var e = (KeyValuePair<object, V>)o;
- object key = e.Key;
- object val = e.Value;
- object v = outerInstance.Get(key);
- return v == null ? val == null : v.Equals(val);
- }
-
- public bool Remove(KeyValuePair<object, V> item)
- {
- throw new System.NotSupportedException();
- }
-
- public int Count { get { return outerInstance.count; } private set { throw new NotSupportedException(); } }
-
- public void Clear()
- {
- if (!allowModify)
- {
- throw new System.NotSupportedException();
- }
- outerInstance.Clear();
- }
- }
-
- /// <summary>
- /// Returns an unmodifiable <seealso cref="CharArrayMap"/>. This allows to provide
- /// unmodifiable views of internal map for "read-only" use.
- /// </summary>
- /// <param name="map">
- /// a map for which the unmodifiable map is returned. </param>
- /// <returns> an new unmodifiable <seealso cref="CharArrayMap"/>. </returns>
- /// <exception cref="NullPointerException">
- /// if the given map is <code>null</code>. </exception>
- public static CharArrayMap<V> UnmodifiableMap<V>(CharArrayMap<V> map)
- {
- if (map == null)
- {
- throw new System.NullReferenceException("Given map is null");
- }
- if (map == EmptyMap() || map.Empty)
- {
- return EmptyMap();
- }
- if (map is UnmodifiableCharArrayMap)
- {
- return map;
- }
- return new UnmodifiableCharArrayMap<V>(map);
- }
-
- /// <summary>
- /// Returns a copy of the given map as a <seealso cref="CharArrayMap"/>. If the given map
- /// is a <seealso cref="CharArrayMap"/> the ignoreCase property will be preserved.
- /// <para>
- /// <b>Note:</b> If you intend to create a copy of another <seealso cref="CharArrayMap"/> where
- /// the <seealso cref="Version"/> of the source map differs from its copy
- /// <seealso cref="#CharArrayMap(Version, Map, boolean)"/> should be used instead.
- /// The <seealso cref="#copy(Version, Map)"/> will preserve the <seealso cref="Version"/> of the
- /// source map it is an instance of <seealso cref="CharArrayMap"/>.
- /// </para>
- /// </summary>
- /// <param name="matchVersion">
- /// compatibility match version see <a href="#version">Version
- /// note</a> above for details. This argument will be ignored if the
- /// given map is a <seealso cref="CharArrayMap"/>. </param>
- /// <param name="map">
- /// a map to copy </param>
- /// <returns> a copy of the given map as a <seealso cref="CharArrayMap"/>. If the given map
- /// is a <seealso cref="CharArrayMap"/> the ignoreCase property as well as the
- /// matchVersion will be of the given map will be preserved. </returns>
- public static CharArrayMap<V> copy(LuceneVersion matchVersion, IDictionary<object, V> map)
- {
- if (map == EMPTY_MAP)
- {
- return EmptyMap();
- }
- if (map is CharArrayMap)
- {
- var m = (CharArrayMap<V>) map;
- // use fast path instead of iterating all values
- // this is even on very small sets ~10 times faster than iterating
- var keys = new char[m.keys.Length][];
- Array.Copy(m.keys, 0, keys, 0, keys.Length);
- var values = new V[m.values.Length];
- Array.Copy(m.values, 0, values, 0, values.Length);
- m = new CharArrayMap<V>(m) {keys = keys, values = values};
- return m;
- }
- return new CharArrayMap<V>(matchVersion, map, false);
- }
-
- /// <summary>
- /// Returns an empty, unmodifiable map. </summary>
- public static CharArrayMap<char[]> EmptyMap()
- {
- return EMPTY_MAP;
- }
-
- // package private CharArraySet instanceof check in CharArraySet
- class UnmodifiableCharArrayMap<V> : CharArrayMap<V>
- {
-
- public UnmodifiableCharArrayMap(CharArrayMap<V> map) : base(map)
- {
-
- }
-
- public override void Clear()
- {
- throw new System.NotSupportedException();
- }
-
- public override V Put(object o, V val)
- {
- throw new System.NotSupportedException();
- }
-
- public override V Put(char[] text, V val)
- {
- throw new System.NotSupportedException();
- }
-
- public override V Put(ICharSequence text, V val)
- {
- throw new System.NotSupportedException();
- }
-
- public override V Put(string text, V val)
- {
- throw new System.NotSupportedException();
- }
-
- public override bool Remove(object key)
- {
- throw new System.NotSupportedException();
- }
-
- override EntrySet CreateEntrySet()
- {
- return new EntrySet(this, false);
- }
- }
-
- /// <summary>
- /// Empty <seealso cref="CharArrayMap{V}.UnmodifiableCharArrayMap"/> optimized for speed.
- /// Contains checks will always return <code>false</code> or throw
- /// NPE if necessary.
- /// </summary>
- private class EmptyCharArrayMap<V> : UnmodifiableCharArrayMap<V>
- {
- public EmptyCharArrayMap():base(new CharArrayMap<V>(LuceneVersion.LUCENE_CURRENT, 0, false))
- {
-
- }
-
- public override bool ContainsKey(char[] text, int off, int len)
- {
- if (text == null)
- {
- throw new System.NullReferenceException();
- }
- return false;
- }
-
- public bool ContainsKey(ICharSequence cs)
- {
- if (cs == null)
- {
- throw new System.NullReferenceException();
- }
- return false;
- }
-
- public override bool ContainsKey(object o)
- {
- if (o == null)
- {
- throw new System.NullReferenceException();
- }
- return false;
- }
-
- public override V Get(char[] text, int off, int len)
- {
- if (text == null)
- {
- throw new System.NullReferenceException();
- }
- return default(V);
- }
-
- public V Get(ICharSequence cs)
- {
- if (cs == null)
- {
- throw new System.NullReferenceException();
- }
- return default(V);
- }
-
- public override V Get(object o)
- {
- if (o == null)
- {
- throw new System.NullReferenceException();
- }
- return default(V);
- }
- }
- }
+ /// <summary>
+ /// A simple class that stores key Strings as char[]'s in a
+ /// hash table. Note that this is not a general purpose
+ /// class. For example, it cannot remove items from the
+ /// map, nor does it resize its hash table to be smaller,
+ /// etc. It is designed to be quick to retrieve items
+ /// by char[] keys without the necessity of converting
+ /// to a String first.
+ ///
+ /// <a name="version"></a>
+ /// <para>You must specify the required <seealso cref="Version"/>
+ /// compatibility when creating <seealso cref="CharArrayMap"/>:
+ /// <ul>
+ /// <li> As of 3.1, supplementary characters are
+ /// properly lowercased.</li>
+ /// </ul>
+ /// Before 3.1 supplementary characters could not be
+ /// lowercased correctly due to the lack of Unicode 4
+ /// support in JDK 1.4. To use instances of
+ /// <seealso cref="CharArrayMap"/> with the behavior before Lucene
+ /// 3.1 pass a <seealso cref="Version"/> < 3.1 to the constructors.
+ /// </para>
+ /// </summary>
+ public class CharArrayMap<V> : IDictionary<object, V>
+ {
+ // private only because missing generics
+ private static readonly CharArrayMap<V> EMPTY_MAP = new EmptyCharArrayMap<V>();
+
+ private const int INIT_SIZE = 8;
+ private readonly CharacterUtils charUtils;
+ private readonly bool ignoreCase;
+ private int count;
+ internal readonly LuceneVersion matchVersion; // package private because used in CharArraySet
+ internal char[][] keys; // package private because used in CharArraySet's non Set-conform CharArraySetIterator
+ internal V[] values; // package private because used in CharArraySet's non Set-conform CharArraySetIterator
+
+ /// <summary>
+ /// Create map with enough capacity to hold startSize terms
+ /// </summary>
+ /// <param name="matchVersion">
+ /// compatibility match version see <a href="#version">Version
+ /// note</a> above for details. </param>
+ /// <param name="startSize">
+ /// the initial capacity </param>
+ /// <param name="ignoreCase">
+ /// <code>false</code> if and only if the set should be case sensitive
+ /// otherwise <code>true</code>. </param>
+ public CharArrayMap(LuceneVersion matchVersion, int startSize, bool ignoreCase)
+ {
+ this.ignoreCase = ignoreCase;
+ var size = INIT_SIZE;
+ while (startSize + (startSize >> 2) > size)
+ {
+ size <<= 1;
+ }
+ keys = new char[size][];
+ values = new V[size];
+ this.charUtils = CharacterUtils.GetInstance(matchVersion);
+ this.matchVersion = matchVersion;
+ }
+
+ /// <summary>
+ /// Creates a map from the mappings in another map.
+ /// </summary>
+ /// <param name="matchVersion">
+ /// compatibility match version see <a href="#version">Version
+ /// note</a> above for details. </param>
+ /// <param name="c">
+ /// a map whose mappings to be copied </param>
+ /// <param name="ignoreCase">
+ /// <code>false</code> if and only if the set should be case sensitive
+ /// otherwise <code>true</code>. </param>
+ public CharArrayMap(LuceneVersion matchVersion, IDictionary<object, V> c, bool ignoreCase)
+ : this(matchVersion, c.Count, ignoreCase)
+ {
+ foreach (var v in c)
+ {
+ Add(v);
+ }
+ }
+
+ /// <summary>
+ /// Lucene.NET specific, in order to support the KeySet functionality without doing much copying.
+ /// </summary>
+ /// <param name="keys"></param>
+ private CharArrayMap(char[][] keys, int count)
+ {
+ this.keys = keys;
+ this.count = count;
+ }
+
+ /// <summary>
+ /// Create set from the supplied map (used internally for readonly maps...) </summary>
+ private CharArrayMap(CharArrayMap<V> toCopy)
+ {
+ this.keys = toCopy.keys;
+ this.values = toCopy.values;
+ this.ignoreCase = toCopy.ignoreCase;
+ this.count = toCopy.count;
+ this.charUtils = toCopy.charUtils;
+ this.matchVersion = toCopy.matchVersion;
+ }
+
+ public void Add(KeyValuePair<object, V> item)
+ {
+ Put(item.Key, item.Value);
+ }
+
+ /// <summary>
+ /// Clears all entries in this map. This method is supported for reusing, but not <seealso cref="Map#remove"/>. </summary>
+ public virtual void Clear()
+ {
+ count = 0;
+ Arrays.Fill(keys, null);
+ Arrays.Fill(values, default(V));
+ }
+
+ public bool Contains(KeyValuePair<object, V> item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void CopyTo(KeyValuePair<object, V>[] array, int arrayIndex)
+ {
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// true if the <code>len</code> chars of <code>text</code> starting at <code>off</code>
+ /// are in the <seealso cref="#keySet()"/>
+ /// </summary>
+ public virtual bool ContainsKey(char[] text, int off, int len)
+ {
+ return keys[GetSlot(text, off, len)] != null;
+ }
+
+ /// <summary>
+ /// true if the <code>CharSequence</code> is in the <seealso cref="#keySet()"/> </summary>
+ public virtual bool ContainsKey(string cs)
+ {
+ return keys[GetSlot(cs)] != null;
+ }
+
+ public virtual bool ContainsKey(object o)
+ {
+ var c = o as char[];
+ if (c != null)
+ {
+ var text = c;
+ return ContainsKey(text, 0, text.Length);
+ }
+ return ContainsKey(o.ToString());
+ }
+
+ public void Add(object key, V value)
+ {
+ Put(key, value);
+ }
+
+ /// <summary>
+ /// returns the value of the mapping of <code>len</code> chars of <code>text</code>
+ /// starting at <code>off</code>
+ /// </summary>
+ public virtual V Get(char[] text, int off, int len)
+ {
+ return values[GetSlot(text, off, len)];
+ }
+
+ /// <summary>
+ /// returns the value of the mapping of the chars inside this {@code CharSequence} </summary>
+ public virtual V Get(string cs)
+ {
+ return values[GetSlot(cs)];
+ }
+
+ public virtual V Get(object o)
+ {
+ var text = o as char[];
+ if (text != null)
+ {
+ return Get(text, 0, text.Length);
+ }
+ return Get(o.ToString());
+ }
+
+ private int GetSlot(char[] text, int off, int len)
+ {
+ int code = GetHashCode(text, off, len);
+ int pos = code & (keys.Length - 1);
+ char[] text2 = keys[pos];
+ if (text2 != null && !Equals(text, off, len, text2))
+ {
+ int inc = ((code >> 8) + code) | 1;
+ do
+ {
+ code += inc;
+ pos = code & (keys.Length - 1);
+ text2 = keys[pos];
+ } while (text2 != null && !Equals(text, off, len, text2));
+ }
+ return pos;
+ }
+
+ /// <summary>
+ /// Returns true if the String is in the set </summary>
+ private int GetSlot(string text)
+ {
+ int code = GetHashCode(text);
+ int pos = code & (keys.Length - 1);
+ char[] text2 = keys[pos];
+ if (text2 != null && !Equals(text, text2))
+ {
+ int inc = ((code >> 8) + code) | 1;
+ do
+ {
+ code += inc;
+ pos = code & (keys.Length - 1);
+ text2 = keys[pos];
+ } while (text2 != null && !Equals(text, text2));
+ }
+ return pos;
+ }
+
+ /// <summary>
+ /// Add the given mapping. </summary>
+ public virtual V Put(ICharSequence text, V value)
+ {
+ return Put(text.ToString(), value); // could be more efficient
+ }
+
+ public virtual V Put(object o, V value)
+ {
+ var c = o as char[];
+ if (c != null)
+ {
+ return Put(c, value);
+ }
+ return Put(o.ToString(), value);
+ }
+
+ /// <summary>
+ /// Add the given mapping. </summary>
+ public virtual V Put(string text, V value)
+ {
+ return Put(text.ToCharArray(), value);
+ }
+
+ /// <summary>
+ /// Add the given mapping.
+ /// If ignoreCase is true for this Set, the text array will be directly modified.
+ /// The user should never modify this text array after calling this method.
+ /// </summary>
+ public virtual V Put(char[] text, V value)
+ {
+ if (ignoreCase)
+ {
+ charUtils.ToLower(text, 0, text.Length);
+ }
+ int slot = GetSlot(text, 0, text.Length);
+ if (keys[slot] != null)
+ {
+ V oldValue = values[slot];
+ values[slot] = value;
+ return oldValue;
+ }
+ keys[slot] = text;
+ values[slot] = value;
+ count++;
+
+ if (count + (count >> 2) > keys.Length)
+ {
+ Rehash();
+ }
+
+ return default(V);
+ }
+
+ private void Rehash()
+ {
+ Debug.Assert(keys.Length == values.Length);
+ int newSize = 2 * keys.Length;
+ char[][] oldkeys = keys;
+ V[] oldvalues = values;
+ keys = new char[newSize][];
+ values = new V[newSize];
+
+ for (int i = 0; i < oldkeys.Length; i++)
+ {
+ char[] text = oldkeys[i];
+ if (text != null)
+ {
+ // todo: could be faster... no need to compare strings on collision
+ int slot = GetSlot(text, 0, text.Length);
+ keys[slot] = text;
+ values[slot] = oldvalues[i];
+ }
+ }
+ }
+
+ private bool Equals(char[] text1, int off, int len, char[] text2)
+ {
+ if (len != text2.Length)
+ {
+ return false;
+ }
+ int limit = off + len;
+ if (ignoreCase)
+ {
+ for (int i = 0; i < len;)
+ {
+ var codePointAt = charUtils.CodePointAt(text1, off + i, limit);
+ if (char.ToLower((char)codePointAt) != charUtils.CodePointAt(text2, i, text2.Length))
+ {
+ return false;
+ }
+ i += Character.CharCount(codePointAt);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < len; i++)
+ {
+ if (text1[off + i] != text2[i])
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private bool Equals(ICharSequence text1, char[] text2)
+ {
+ int len = text1.Length;
+ if (len != text2.Length)
+ {
+ return false;
+ }
+ if (ignoreCase)
+ {
+ for (int i = 0; i < len;)
+ {
+ int codePointAt = charUtils.CodePointAt(text1, i);
+ if (char.ToLower((char)codePointAt) != charUtils.CodePointAt(text2, i, text2.Length))
+ {
+ return false;
+ }
+ i += Character.CharCount(codePointAt);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < len; i++)
+ {
+ if (text1.CharAt(i) != text2[i])
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private int GetHashCode(char[] text, int offset, int len)
+ {
+ if (text == null)
+ {
+ throw new ArgumentException("text can't be null", "text");
+ }
+ int code = 0;
+ int stop = offset + len;
+ if (ignoreCase)
+ {
+ for (int i = offset; i < stop;)
+ {
+ int codePointAt = charUtils.CodePointAt(text, i, stop);
+ code = code * 31 + char.ToLower((char)codePointAt);
+ i += Character.CharCount(codePointAt);
+ }
+ }
+ else
+ {
+ for (int i = offset; i < stop; i++)
+ {
+ code = code * 31 + text[i];
+ }
+ }
+ return code;
+ }
+
+ private int GetHashCode(string text)
+ {
+ if (text == null)
+ {
+ throw new ArgumentException("text can't be null", "text");
+ }
+ int code = 0;
+ int len = text.Length;
+ if (ignoreCase)
+ {
+ for (int i = 0; i < len;)
+ {
+ int codePointAt = charUtils.CodePointAt(text, i);
+ code = code * 31 + char.ToLower((char)codePointAt);
+ i += Character.CharCount(codePointAt);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < len; i++)
+ {
+ code = code * 31 + text[i];
+ }
+ }
+ return code;
+ }
+
+ public virtual bool Remove(object key)
+ {
+ throw new NotSupportedException();
+ }
+
+ public bool TryGetValue(object key, out V value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public V this[object key]
+ {
+ get { return Get(key); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public ICollection<object> Keys { get { return KeySet(); } }
+
+ public ICollection<V> Values { get { return values; } }
+
+ public bool Remove(KeyValuePair<object, V> item)
+ {
+ throw new NotSupportedException();
+ }
+
+ public int Count
+ {
+ get
+ {
+ {
+ return count;
+ }
+ }
+ }
+
+ public bool IsReadOnly { get; private set; }
+
+ public IEnumerator<KeyValuePair<object, V>> GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override string ToString()
+ {
+ var sb = new StringBuilder("{");
+ foreach (KeyValuePair<object, V> entry in GetEntrySet())
+ {
+ if (sb.Length > 1)
+ {
+ sb.Append(", ");
+ }
+ sb.Append(entry);
+ }
+ return sb.Append('}').ToString();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ private EntrySet entrySet = null;
+ private CharArraySet keySet = null;
+
+ protected virtual EntrySet CreateEntrySet()
+ {
+ return new EntrySet(this, true);
+ }
+
+ public EntrySet GetEntrySet()
+ {
+ if (entrySet == null)
+ {
+ entrySet = CreateEntrySet();
+ }
+ return entrySet;
+ }
+
+ // helper for CharArraySet to not produce endless recursion
+ // TODO LUCENENET
+ private ISet<object> originalKeySet;
+ internal ISet<object> OriginalKeySet()
+ {
+ return originalKeySet ?? (originalKeySet = new LightWrapperSet(this));
+ }
+
+ private class LightWrapperSet : ISet<object>
+ {
+ private readonly CharArrayMap<V> map;
+
+ public LightWrapperSet(CharArrayMap<V> map)
+ {
+ this.map = map;
+ }
+
+ public IEnumerator<object> GetEnumerator()
+ {
+ return map.Keys.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public void Add(object item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void UnionWith(IEnumerable<object> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void IntersectWith(IEnumerable<object> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ExceptWith(IEnumerable<object> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SymmetricExceptWith(IEnumerable<object> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsSubsetOf(IEnumerable<object> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsSupersetOf(IEnumerable<object> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsProperSupersetOf(IEnumerable<object> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsProperSubsetOf(IEnumerable<object> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Overlaps(IEnumerable<object> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool SetEquals(IEnumerable<object> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool ISet<object>.Add(object item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Clear()
+ {
+ map.Clear();
+ }
+
+ public bool Contains(object item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void CopyTo(object[] array, int arrayIndex)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Remove(object item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public int Count { get { return map.Count; } }
+ public bool IsReadOnly { get { return map.IsReadOnly; } }
+ }
+
+ /// <summary>
+ /// Returns an <seealso cref="CharArraySet"/> view on the map's keys.
+ /// The set will use the same {@code matchVersion} as this map.
+ /// </summary>
+ private CharArraySet KeySet()
+ {
+ if (keySet == null)
+ {
+ // prevent adding of entries
+ keySet = new UnmodifiableCharArraySet(new CharArrayMap<object>(this.keys, this.count));
+ }
+ return keySet;
+ }
+
+ private sealed class UnmodifiableCharArraySet : CharArraySet
+ {
+ internal UnmodifiableCharArraySet(CharArrayMap<object> map) : base(map)
+ {
+ }
+
+ public override bool Add(object o)
+ {
+ throw new NotSupportedException();
+ }
+ public bool Add(ICharSequence text)
+ {
+ throw new NotSupportedException();
+ }
+ public override bool Add(string text)
+ {
+ throw new NotSupportedException();
+ }
+ public override bool Add(char[] text)
+ {
+ throw new NotSupportedException();
+ }
+ }
+
+ /// <summary>
+ /// public iterator class so efficient methods are exposed to users
+ /// </summary>
+ public class EntryIterator : IEnumerator<KeyValuePair<object, V>>
+ {
+ private readonly CharArrayMap<V> outerInstance;
+
+ internal int pos = -1;
+ internal int lastPos;
+ internal readonly bool allowModify;
+
+ internal EntryIterator(CharArrayMap<V> outerInstance, bool allowModify)
+ {
+ this.outerInstance = outerInstance;
+ this.allowModify = allowModify;
+ GoNext();
+ }
+
+ internal void GoNext()
+ {
+ lastPos = pos;
+ pos++;
+ while (pos < outerInstance.keys.Length && outerInstance.keys[pos] == null)
+ {
+ pos++;
+ }
+ }
+
+ public bool HasNext()
+ {
+ return pos < outerInstance.keys.Length;
+ }
+
+ /// <summary>
+ /// gets the next key... do not modify the returned char[] </summary>
+ public virtual char[] NextKey()
+ {
+ GoNext();
+ return outerInstance.keys[lastPos];
+ }
+
+ /// <summary>
+ /// gets the next key as a newly created String object </summary>
+ public virtual string NextKeyString()
+ {
+ return new string(NextKey());
+ }
+
+ /// <summary>
+ /// returns the value associated with the last key returned </summary>
+ public virtual V CurrentValue()
+ {
+ return outerInstance.values[lastPos];
+ }
+
+ /// <summary>
+ /// sets the value associated with the last key returned </summary>
+ public virtual V SetValue(V value)
+ {
+ if (!allowModify)
+ {
+ throw new System.NotSupportedException();
+ }
+ V old = outerInstance.values[lastPos];
+ outerInstance.values[lastPos] = value;
+ return old;
+ }
+
+ /// <summary>
+ /// use nextCharArray() + currentValue() for better efficiency.
+ /// </summary>
+ //public KeyValuePair<object, V> Next()
+ //{
+ // GoNext();
+ // //return new KeyValuePair<object, V>();
+ // return new MapEntry(outerInstance, lastPos, allowModify);
+ //}
+
+ public void Remove()
+ {
+ throw new NotSupportedException();
+ }
+
+ #region Added for better .NET support
+ public void Dispose()
+ {
+ }
+
+ public bool MoveNext()
+ {
+ if (!HasNext()) return false;
+ GoNext();
+ return true;
+ }
+
+ public void Reset()
+ {
+ pos = -1;
+ GoNext();
+ }
+
+ public KeyValuePair<object, V> Current { get { return new KeyValuePair<object, V>(outerInstance.keys[lastPos], outerInstance.values[lastPos]); } private set { } }
+
+ object IEnumerator.Current
+ {
+ get { return CurrentValue(); }
+ }
+ #endregion
+ }
+
+ /// <summary>
+ /// public EntrySet class so efficient methods are exposed to users
+ /// </summary>
+ public sealed class EntrySet : ISet<KeyValuePair<object, V>>
+ {
+ private readonly CharArrayMap<V> outerInstance;
+
+ internal readonly bool allowModify;
+
+ internal EntrySet(CharArrayMap<V> outerInstance, bool allowModify)
+ {
+ this.outerInstance = outerInstance;
+ this.allowModify = allowModify;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return new EntryIterator(outerInstance, allowModify);
+ }
+
+ public bool Contains(object o)
+ {
+ if (!(o is DictionaryEntry))
+ {
+ return false;
+ }
+ var e = (KeyValuePair<object, V>)o;
+ object key = e.Key;
+ object val = e.Value;
+ object v = outerInstance.Get(key);
+ return v == null ? val == null : v.Equals(val);
+ }
+
+ public void CopyTo(KeyValuePair<object, V>[] array, int arrayIndex)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Remove(KeyValuePair<object, V> item)
+ {
+ throw new NotSupportedException();
+ }
+
+ public int Count { get { return outerInstance.count; } private set { throw new NotSupportedException(); } }
+ public bool IsReadOnly { get; }
+
+ #region Not implemented members
+
+ IEnumerator<KeyValuePair<object, V>> IEnumerable<KeyValuePair<object, V>>.GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Add(KeyValuePair<object, V> item)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void UnionWith(IEnumerable<KeyValuePair<object, V>> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void IntersectWith(IEnumerable<KeyValuePair<object, V>> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ExceptWith(IEnumerable<KeyValuePair<object, V>> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void SymmetricExceptWith(IEnumerable<KeyValuePair<object, V>> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsSubsetOf(IEnumerable<KeyValuePair<object, V>> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsSupersetOf(IEnumerable<KeyValuePair<object, V>> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsProperSupersetOf(IEnumerable<KeyValuePair<object, V>> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsProperSubsetOf(IEnumerable<KeyValuePair<object, V>> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool Overlaps(IEnumerable<KeyValuePair<object, V>> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool SetEquals(IEnumerable<KeyValuePair<object, V>> other)
+ {
+ throw new NotImplementedException();
+ }
+
+ bool ISet<KeyValuePair<object, V>>.Add(KeyValuePair<object, V> item)
+ {
+ throw new NotImplementedException();
+ }
+ #endregion
+
+ public void Clear()
+ {
+ if (!allowModify)
+ {
+ throw new NotSupportedException();
+ }
+ outerInstance.Clear();
+ }
+
+ public bool Contains(KeyValuePair<object, V> item)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ /// <summary>
+ /// Returns an unmodifiable <seealso cref="CharArrayMap"/>. This allows to provide
+ /// unmodifiable views of internal map for "read-only" use.
+ /// </summary>
+ /// <param name="map">
+ /// a map for which the unmodifiable map is returned. </param>
+ /// <returns> an new unmodifiable <seealso cref="CharArrayMap"/>. </returns>
+ /// <exception cref="NullPointerException">
+ /// if the given map is <code>null</code>. </exception>
+ public static CharArrayMap<V> UnmodifiableMap(CharArrayMap<V> map)
+ {
+ if (map == null)
+ {
+ throw new ArgumentException("Given map is null", nameof(map));
+ }
+ if (map == EmptyMap() || map.Count == 0)
+ {
+ return EmptyMap();
+ }
+ if (map is UnmodifiableCharArrayMap<V>)
+ {
+ return map;
+ }
+ return new UnmodifiableCharArrayMap<V>(map);
+ }
+
+ /// <summary>
+ /// Returns a copy of the given map as a <seealso cref="CharArrayMap"/>. If the given map
+ /// is a <seealso cref="CharArrayMap"/> the ignoreCase property will be preserved.
+ /// <para>
+ /// <b>Note:</b> If you intend to create a copy of another <seealso cref="CharArrayMap"/> where
+ /// the <seealso cref="Version"/> of the source map differs from its copy
+ /// <seealso cref="#CharArrayMap(Version, Map, boolean)"/> should be used instead.
+ /// The <seealso cref="#copy(Version, Map)"/> will preserve the <seealso cref="Version"/> of the
+ /// source map it is an instance of <seealso cref="CharArrayMap"/>.
+ /// </para>
+ /// </summary>
+ /// <param name="matchVersion">
+ /// compatibility match version see <a href="#version">Version
+ /// note</a> above for details. This argument will be ignored if the
+ /// given map is a <seealso cref="CharArrayMap"/>. </param>
+ /// <param name="map">
+ /// a map to copy </param>
+ /// <returns> a copy of the given map as a <seealso cref="CharArrayMap"/>. If the given map
+ /// is a <seealso cref="CharArrayMap"/> the ignoreCase property as well as the
+ /// matchVersion will be of the given map will be preserved. </returns>
+ public static CharArrayMap<V> Copy(LuceneVersion matchVersion, IDictionary<object, V> map)
+ {
+ if (map == EMPTY_MAP)
+ {
+ return EmptyMap();
+ }
+
+ var vs = map as CharArrayMap<V>;
+ if (vs != null)
+ {
+ var m = vs;
+ // use fast path instead of iterating all values
+ // this is even on very small sets ~10 times faster than iterating
+ var keys = new char[m.keys.Length][];
+ Array.Copy(m.keys, 0, keys, 0, keys.Length);
+ var values = new V[m.values.Length];
+ Array.Copy(m.values, 0, values, 0, values.Length);
+ m = new CharArrayMap<V>(m) { keys = keys, values = values };
+ return m;
+ }
+ return new CharArrayMap<V>(matchVersion, map, false);
+ }
+
+ /// <summary>
+ /// Returns an empty, unmodifiable map. </summary>
+ public static CharArrayMap<V> EmptyMap()
+ {
+ return EMPTY_MAP;
+ }
+
+ // package private CharArraySet instanceof check in CharArraySet
+ internal class UnmodifiableCharArrayMap<V> : CharArrayMap<V>
+ {
+
+ public UnmodifiableCharArrayMap(CharArrayMap<V> map) : base(map)
+ {
+
+ }
+
+ public override void Clear()
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public override V Put(object o, V val)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public override V Put(char[] text, V val)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public override V Put(ICharSequence text, V val)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public override V Put(string text, V val)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public override bool Remove(object key)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ protected override EntrySet CreateEntrySet()
+ {
+ return new EntrySet(this, false);
+ }
+ }
+
+ /// <summary>
+ /// Empty <seealso cref="CharArrayMap{V}.UnmodifiableCharArrayMap"/> optimized for speed.
+ /// Contains checks will always return <code>false</code> or throw
+ /// NPE if necessary.
+ /// </summary>
+ private class EmptyCharArrayMap<V> : UnmodifiableCharArrayMap<V>
+ {
+ public EmptyCharArrayMap() : base(new CharArrayMap<V>(LuceneVersion.LUCENE_CURRENT, 0, false))
+ {
+
+ }
+
+ public override bool ContainsKey(char[] text, int off, int len)
+ {
+ if (text == null)
+ {
+ throw new NullReferenceException();
+ }
+ return false;
+ }
+
+ public bool ContainsKey(ICharSequence cs)
+ {
+ if (cs == null)
+ {
+ throw new NullReferenceException();
+ }
+ return false;
+ }
+
+ public override bool ContainsKey(object o)
+ {
+ if (o == null)
+ {
+ throw new NullReferenceException();
+ }
+ return false;
+ }
+
+ public override V Get(char[] text, int off, int len)
+ {
+ if (text == null)
+ {
+ throw new NullReferenceException();
+ }
+ return default(V);
+ }
+
+ public V Get(ICharSequence cs)
+ {
+ if (cs == null)
+ {
+ throw new NullReferenceException();
+ }
+ return default(V);
+ }
+
+ public override V Get(object o)
+ {
+ if (o == null)
+ {
+ throw new NullReferenceException();
+ }
+ return default(V);
+ }
+ }
+ }
}
\ No newline at end of file