You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2022/11/17 19:53:33 UTC
[lucenenet] branch master updated: BREAKING: Refactored CharArraySet and CharArrayMap (now CharArrayDictionary) (#762)
This is an automated email from the ASF dual-hosted git repository.
nightowl888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git
The following commit(s) were added to refs/heads/master by this push:
new 987274e99 BREAKING: Refactored CharArraySet and CharArrayMap (now CharArrayDictionary) (#762)
987274e99 is described below
commit 987274e99cecc5a3530d9348848a92ce14dec30a
Author: Shad Storhaug <sh...@shadstorhaug.com>
AuthorDate: Fri Nov 18 02:53:28 2022 +0700
BREAKING: Refactored CharArraySet and CharArrayMap (now CharArrayDictionary) (#762)
* BUG: Lucene.Net.Analysis.Util (CharArraySet + CharArrayMap): Fixed IsReadOnly flag to return the proper value reflecting read-only state. Added tests.
* Lucene.Net.Analysis.Util (CharArraySet + CharArrayMap): Don't call overridable members in constructor (See #670). Added some missing guard clauses.
* BREAKING: Lucene.Net.Analysis.Util (CharArraySet + CharArrayMap): Removed Remove(), IntersectWith(), ExceptWith(), SymmetricExceptWith(), Contains(KeyValuePair) from public APIs by implementing collection interfaces explicitly.
* Lucene.Net.Analysis.Util (CharArraySet + CharArrayMap): Added ToCharArraySet() and ToCharArrayMap() methods and extension methods to make copying collections easier.
* BREAKING: Lucene.Net.Analysis.Util.CharArrayMap: Renamed EntryIterator > Enumerator, removed HasNext, NextKey(), and NextKeyString(), added CurrentKey and CurrentKeyString properties. Removed EntrySet_ class, EntrySet() method.
* BREAKING: Lucene.Net.Analysis.Util: Renamed CharArrayMap > CharArrayDictionary.
* BREAKING: Lucene.Net.Analysis.Util.CharArrayDictionary: Removed EmptyMap() method and created public Empty static field to replace it.
* BREAKING: Lucene.Net.Analysis.Util.CharArraySet: Renamed EMPTY_SET > Empty.
* Lucene.Net.Analysis.Util.CharArrayDictionary: Added missing guard clauses and updated documentation.
* PERFORMANCE: Lucene.Net.Analysis.Util.CharArrayMap: Use CurrentKeyString and CurrentKeyValue to avoid allocation of KeyValuePair
* BUG: Lucene.Net.Analysis.Util.CharArrayMap::Equals(): Use JCG.EqualityComparer when comparing values for equality.
* Lucene.Net.Analysis.Util.CharArraySet: Added missing guard clauses and added documentation.
* PERFORMANCE/BUG: Lucene.Net.Analysis.Util.CharArrayDictionary: Added cases for string and ICharSequence to object overload of PutImpl, ContainsKey, Get, and TryGetValue. Convert unknown types to string in invariant context.
* PERFORMANCE: Lucene.Net.Analysis.Util.CharArrayDictionary: Added optimized PutImpl(string, MapValue) implementation that only allocates a char[] if it is required.
* PERFORMANCE: Lucene.Net.Analysis.Util.CharArrayDictionary: Added Set/SetImpl methods that don't look up the previous value for use in the CharArrayDictionary.this[] overloads.
* Lucene.Net.Analysis.Util.CharArraySet: Changed signature of UnionWith(IEnumerable<string>) to return a bool instead of void. Added explicit interface implementation to adhere to the ISet<string> contract.
* BREAKING: Lucene.Net.Analysis.Util.CharArraySet: Marked ContainsAll() overloads obsolete, since this is duplicate functionality of ISet<T>.IsSupersetOf().
* BREAKING: Lucene.Net.Analysis.Util.CharArrayDictionary: Moved OriginalKeySet property from the public API to explicitly defined on the ICharArrayDictionary interface. Previously it was hidden from Intellisense, so this will have minimal impact.
* Lucene.Net.Analysis.Util (CharArrayDictionary + CharArraySet): Consolidated KeyCollection and UnmodifiableCharArraySet into a single KeyCollection enumerator. Migrated KeyCollection.KeyEnumerator to CharArraySet and renamed it Enumerator. Added ICharArrayDictionaryEnumerator so the necessary members are visible without using generics.
* Lucene.Net.Analysis.Util.CharArrayDictionary: Added documentation to Put() methods that accept a value indicating that this[key] = value is more efficient if the return value is unused.
* PERFORMANCE: Lucene.Net.Analysis.Common: Updated all classes that use CharArrayDictionary<TValue>.Put() and discard the value to use CharArrayDictionary<TValue>.this[] instead.
* Lucene.Net.Analysis.CharArrayDictionary: Added Set() overloads to use to populate CharArraySet
* BREAKING: Lucene.Net.Analysis.Util.CharArraySet::ctor(): Renamed parameter from c > collection.
* Lucene.Net.Analysis.Util.CharArraySet: Added constructor overloads for ICollection<char[]> and ICollection<ICharSequence>.
* Lucene.Net.Analysis.Util.CharArrayDictionary::Copy(): Use pattern matching when converting to CharArrayDictionary<TValue>
* PERFORMANCE: Lucene.Net.Analysis.Util.CharArrayDictionary: Fixed enumerators to use CurrentKey and CurrentValue where appropriate to reduce allocations
* Lucene.Net.Analysis.Util.CharArrayDictionary: Added KeyValuePair<char[], TValue> overload of CopyTo
* Lucene.Net.Analysis.Util.CharArraySet: Fixed implementation of SetEquals() so it matches any IEnumerable<T> type with the same values (accounting for case sensitivity). Added overloads for IEnumerable<char[]>, IEnumerable<ICharSequence> and IEnumerable<T> (object). Added tests.
* Lucene.Net.Analysis.Util.CharArrayDictionary<TValue>: Added error checking to ensure enumerator instances throw InvalidOperationException when the collection state is mutated, or the enumerator is positioned before or after the bounds of the collection.
* Lucene.Net.Analysis.Util.CharArraySet: Added overloads for IEnumerable<char[]> and IEnumerable<ICharSequence> for IsSubset(), IsSuperset(), IsProperSubset() and IsProperSuperset() + tests.
* Lucene.Net.Analysis.Util.CharArraySet: Added overloads of CopyTo() for IList<char[]> and ICharSequence[].
* Lucene.Net.Analysis.Util.CharArraySet: Added tests for IsSubset(), IsProperSubset(), IsSuperset(), IsProperSuperset(), Overlaps(), SetEquals() with null values in the comparison set. Added overloads of char[] and ICharSequence for Overlaps().
* Lucene.Net.Analysis.Util.CharArrayDictionary: Added CopyTo() overload for ICharSequence + added tests for all 3 overloads
* BREAKING: Lucene.Net.Analysis.Util (CharArraySet + CharArrayDictionary<TValue>): Renamed constructor parameters c > collection, startSize > capacity. Changed type of collection from ICollection<T> to IEnumerable<T> to match .NET collections.
* Lucene.Net.Analysis.Util.CharArrayDictionary<TValue>::ToString(): Print "null" when there is a null value to match Java.
* BREAKING: Lucene.Net.Analysis.Util.CharArraySet: Changed parameter type of Copy() and CopySet() methods from ICollection<T> to IEnumerable<T>. Renamed the parameter from set > collection.
* BUG: Lucene.Net.Analysis.Util.CharArrayDictionary<TValue>::ctor(): Don't call virtual methods in the constructor.
* Lucene.Net.Analysis.Util (CharArraySet + CharArrayDictionary): Implemented standard interfaces for collections and enumerators. Consolidated error messages in new SR class.
* BREAKING: Lucene.Net.Analysis.Util.CharArrayDictionary: Removed Get() overloads from the public API. Refactored them to throw KeyNotFoundException instead of returning default(TValue). Enabled nullable reference type support and fixed warnings.
* BREAKING: Lucene.Net.Analysis.Util.CharArrayDictionary: Refactored Put() overloads allow for value types without requiring them to be made nullable. The signature was changed to return a bool and the previousValue (that was returned before) was made into an out parameter.
* BREAKING: Lucene.Net.Analysis.Util (CharArraySet + CharArrayDictionary): Changed all object overloads of common methods from object to T to allow passing through value types without boxing.
* Lucene.Net.Analysis.Util (CharArraySet + CharArrayDictionary): Reworked ConvertObjectToChars() and optimized ICharSequence paths. Fixed both to check ICharSequence.HasValue before using and throw ArgumentNullException if it is not true when setting keys.
* BREAKING: Removed Lucene.Net.Analysis.Util.CharArraySetExtensions. These are edge cases that are now handled by ConvertObjectToChars().
* BREAKING: Removed Lucene.Net.Analysis.Util.CharArrayDictionaryExtensions. These are edge cases that are now handled by ConvertObjectToChars().
* PERFORMANCE: Lucene.Net.Analysis.Util.CharArrayDictionary::Copy(): Use Span<T> when copying the dictionary/set.
* Lucene.Net.Analysis.Util.CharArrayDictionary.Enumerator::CurrentValue: Set to MaybeNull to match SetValue()
* Lucene.Net.Analysis.Util (CharArraySet + CharArrayDictionary): Added documentation for public members
* Lucene.Net.Analysis.Util.CharArrayDictionary: Renamed UnmodifiableCharArrayDictionary > ReadOnlyCharArrayDictionary to conform with .NET conventions.
* BREAKING: Lucene.Net.Analysis.Util (CharArraySet + CharArrayDictionary): Renamed all method parameters to be consistently using text (instead of key) and startIndex (instead of offset)
* BUG: Lucene.Net.Analysis.Util: Fixed this[char[], int, int] setter so it will correctly set an array representing startIndex and length as the key. Added overloads of Put() to allow setting slices of char[].
* Lucene.Net.Analysis.Util.CharArraySet: Added overloads of Add() to allow setting slices of char[].
* Lucene.Net.Analysis.Util.CharArrayDictionary: Fixed Set() and Add() overloads
* BREAKING: Lucene.Net.Analysis.Util: Removed Put() overloads that don't accept a value from the public API. They were only intended to be used by CharArraySet.
* BREAKING: Removed Add(KeyValuePair<string, TValue>) overload from the public API.
* Lucene.Net.Analysis.Util.CharArrayDictionary: Added constructor overloads for char[] and ICharSequence.
* BUG: Lucene.Net.Analysis.Util.CharArraySet::Empty: Changed empty generic closing type for the related CharArrayDictionary from string to object.
* Lucene.Net.Analysis.Util: Changed extension methods to use IEnumerable<T> for better interop with LINQ.
---
Directory.Build.targets | 18 +-
.../Analysis/Ar/ArabicAnalyzer.cs | 2 +-
.../Analysis/Bg/BulgarianAnalyzer.cs | 2 +-
.../Analysis/Br/BrazilianAnalyzer.cs | 2 +-
.../Analysis/Ca/CatalanAnalyzer.cs | 2 +-
.../Analysis/CharFilter/HTMLStripCharFilter.cs | 14 +-
.../Analysis/Ckb/SoraniAnalyzer.cs | 2 +-
.../Analysis/Core/StopFilter.cs | 16 +-
.../Analysis/Cz/CzechAnalyzer.cs | 2 +-
.../Analysis/Da/DanishAnalyzer.cs | 2 +-
.../Analysis/De/GermanAnalyzer.cs | 2 +-
.../Analysis/En/EnglishAnalyzer.cs | 2 +-
.../Analysis/En/KStemmer.cs | 45 +-
.../Analysis/Es/SpanishAnalyzer.cs | 2 +-
.../Analysis/Eu/BasqueAnalyzer.cs | 2 +-
.../Analysis/Fi/FinnishAnalyzer.cs | 2 +-
.../Analysis/Fr/FrenchAnalyzer.cs | 2 +-
.../Analysis/Ga/IrishAnalyzer.cs | 2 +-
.../Analysis/Gl/GalicianAnalyzer.cs | 2 +-
.../Analysis/Hi/HindiAnalyzer.cs | 2 +-
.../Analysis/Hu/HungarianAnalyzer.cs | 2 +-
.../Analysis/Hunspell/Stemmer.cs | 5 +-
.../Analysis/Hy/ArmenianAnalyzer.cs | 2 +-
.../Analysis/Id/IndonesianAnalyzer.cs | 2 +-
.../Analysis/It/ItalianAnalyzer.cs | 2 +-
.../Analysis/Lv/LatvianAnalyzer.cs | 2 +-
.../Analysis/Nl/DutchAnalyzer.cs | 36 +-
.../Analysis/Nl/DutchStemFilter.cs | 4 +-
.../Analysis/No/NorwegianAnalyzer.cs | 2 +-
.../Analysis/Pt/PortugueseAnalyzer.cs | 2 +-
.../Analysis/Ro/RomanianAnalyzer.cs | 2 +-
.../Analysis/Ru/RussianAnalyzer.cs | 2 +-
.../Analysis/Sv/SwedishAnalyzer.cs | 2 +-
.../Analysis/Synonym/SlowSynonymFilter.cs | 6 +-
.../Analysis/Synonym/SlowSynonymMap.cs | 11 +-
.../Analysis/Tr/TurkishAnalyzer.cs | 2 +-
.../Analysis/Util/CharArrayMap.cs | 4233 ++++++++++++--------
.../Analysis/Util/CharArraySet.cs | 2228 +++++++----
.../Analysis/Util/StopwordAnalyzerBase.cs | 2 +-
.../Analysis/Util/WordlistLoader.cs | 4 +-
.../Uk/UkrainianMorfologikAnalyzer.cs | 2 +-
.../SmartChineseAnalyzer.cs | 4 +-
.../Pl/PolishAnalyzer.cs | 2 +-
.../Analysis/Ar/TestArabicAnalyzer.cs | 4 +-
.../Analysis/Bg/TestBulgarianAnalyzer.cs | 4 +-
.../Analysis/Br/TestBrazilianStemmer.cs | 2 +-
.../Analysis/Cjk/TestCJKAnalyzer.cs | 2 +-
.../Analysis/Ckb/TestSoraniAnalyzer.cs | 6 +-
.../Analysis/Core/TestRandomChains.cs | 6 +-
.../Analysis/Cz/TestCzechAnalyzer.cs | 2 +-
.../Analysis/De/TestGermanAnalyzer.cs | 2 +-
.../Analysis/Fr/TestFrenchAnalyzer.cs | 6 +-
.../Analysis/Nl/TestDutchStemmer.cs | 14 +-
.../Analysis/Synonym/TestSynonymMap.cs | 4 +-
.../Analysis/Th/TestThaiAnalyzer.cs | 8 +-
.../Analysis/Util/TestCharArrayMap.cs | 435 +-
.../Analysis/Util/TestCharArraySet.cs | 886 +++-
.../Support/TestApiConsistency.cs | 2 +-
.../Icu/Segmentation/TestWithCJKBigramFilter.cs | 4 +-
.../Suggest/Analyzing/BlendedInfixSuggesterTest.cs | 10 +-
src/Lucene.Net/Support/DictionaryExtensions.cs | 2 +-
61 files changed, 5403 insertions(+), 2680 deletions(-)
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 3065ed7af..cfd7fd835 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -22,15 +22,23 @@
<Import Project=".build/dependencies.props" Condition="Exists('.build/dependencies.props')" />
+ <!-- Features in .NET 6.x only -->
+ <PropertyGroup Condition=" $(TargetFramework.StartsWith('net6.')) ">
+
+ <DefineConstants>$(DefineConstants);FEATURE_SPANFORMATTABLE</DefineConstants>
+
+ </PropertyGroup>
+
<!-- Features in .NET 5.x and .NET 6.x only -->
<PropertyGroup Condition=" $(TargetFramework.StartsWith('net5.')) Or $(TargetFramework.StartsWith('net6.')) ">
<DefineConstants>$(DefineConstants);FEATURE_ASPNETCORE_ENDPOINT_CONFIG</DefineConstants>
+ <DefineConstants>$(DefineConstants);FEATURE_READONLYSET</DefineConstants>
</PropertyGroup>
<!-- Features in .NET Core 3.x, .NET 5.x, and .NET 6.x only -->
- <PropertyGroup Condition=" $(TargetFramework.StartsWith('netcoreapp3.')) Or $(TargetFramework.StartsWith('net5.')) Or '$(TargetFramework)' == 'net6.0' ">
+ <PropertyGroup Condition=" $(TargetFramework.StartsWith('netcoreapp3.')) Or $(TargetFramework.StartsWith('net5.')) Or $(TargetFramework.StartsWith('net6.')) ">
<DefineConstants>$(DefineConstants);FEATURE_ARGITERATOR</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_DICTIONARY_REMOVE_CONTINUEENUMERATION</DefineConstants>
@@ -39,7 +47,7 @@
</PropertyGroup>
<!-- Features in .NET Standard, .NET Core, .NET 5.x, and .NET 6.x only (no .NET Framework support) -->
- <PropertyGroup Condition=" $(TargetFramework.StartsWith('netstandard')) Or $(TargetFramework.StartsWith('netcoreapp')) Or '$(TargetFramework)' == 'net5.0' Or '$(TargetFramework)' == 'net6.0' ">
+ <PropertyGroup Condition=" $(TargetFramework.StartsWith('netstandard')) Or $(TargetFramework.StartsWith('netcoreapp')) Or $(TargetFramework.StartsWith('net5.')) Or $(TargetFramework.StartsWith('net6.')) ">
<DefineConstants>$(DefineConstants);NETSTANDARD</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_ARRAYEMPTY</DefineConstants>
@@ -50,7 +58,7 @@
</PropertyGroup>
<!-- Features in .NET Standard 2.1, .NET 5.x, and .NET 6.x only -->
- <PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' Or $(TargetFramework.StartsWith('netcoreapp3.')) Or '$(TargetFramework)' == 'net5.0' Or '$(TargetFramework)' == 'net6.0' ">
+ <PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' Or $(TargetFramework.StartsWith('netcoreapp3.')) Or $(TargetFramework.StartsWith('net5.')) Or $(TargetFramework.StartsWith('net6.')) ">
<DefineConstants>$(DefineConstants);FEATURE_CONDITIONALWEAKTABLE_ENUMERATOR</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_CONDITIONALWEAKTABLE_ADDORUPDATE</DefineConstants>
@@ -61,14 +69,14 @@
</PropertyGroup>
<!-- Features in .NET Standard 2.x, .NET Core 2.x, .NET Core 3.x, .NET 5.x, and .NET 6.x -->
- <PropertyGroup Condition=" $(TargetFramework.StartsWith('netstandard2.')) Or $(TargetFramework.StartsWith('netcoreapp2.')) Or $(TargetFramework.StartsWith('netcoreapp3.')) Or '$(TargetFramework)' == 'net5.0' Or '$(TargetFramework)' == 'net6.0' ">
+ <PropertyGroup Condition=" $(TargetFramework.StartsWith('netstandard2.')) Or $(TargetFramework.StartsWith('netcoreapp2.')) Or $(TargetFramework.StartsWith('netcoreapp3.')) Or $(TargetFramework.StartsWith('net5.')) Or $(TargetFramework.StartsWith('net6.')) ">
<DefineConstants>$(DefineConstants);FEATURE_ICONFIGURATIONROOT_PROVIDERS</DefineConstants>
</PropertyGroup>
<!-- Features in .NET Framework 4.5+, .NET Standard 2.x, .NET Core 2.x, .NET Core 3.x, .NET 5.x, and .NET 6.x -->
- <PropertyGroup Condition=" $(TargetFramework.StartsWith('net4')) Or $(TargetFramework.StartsWith('netstandard2.')) Or $(TargetFramework.StartsWith('netcoreapp2.')) Or $(TargetFramework.StartsWith('netcoreapp3.')) Or '$(TargetFramework)' == 'net5.0' Or '$(TargetFramework)' == 'net6.0' ">
+ <PropertyGroup Condition=" $(TargetFramework.StartsWith('net4')) Or $(TargetFramework.StartsWith('netstandard2.')) Or $(TargetFramework.StartsWith('netcoreapp2.')) Or $(TargetFramework.StartsWith('netcoreapp3.')) Or $(TargetFramework.StartsWith('net5.')) Or $(TargetFramework.StartsWith('net6.')) ">
<DefineConstants>$(DefineConstants);FEATURE_ASSEMBLY_GETCALLINGASSEMBLY</DefineConstants>
<DefineConstants>$(DefineConstants);FEATURE_FILESTREAM_LOCK</DefineConstants>
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Ar/ArabicAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Ar/ArabicAnalyzer.cs
index 7e91bdd8a..041bfcb40 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Ar/ArabicAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Ar/ArabicAnalyzer.cs
@@ -99,7 +99,7 @@ namespace Lucene.Net.Analysis.Ar
/// <param name="stopwords">
/// a stopword set </param>
public ArabicAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Bg/BulgarianAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Bg/BulgarianAnalyzer.cs
index 63f9a550d..5c121f82f 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Bg/BulgarianAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Bg/BulgarianAnalyzer.cs
@@ -89,7 +89,7 @@ namespace Lucene.Net.Analysis.Bg
/// Builds an analyzer with the given stop words.
/// </summary>
public BulgarianAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Br/BrazilianAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Br/BrazilianAnalyzer.cs
index 5c8661019..83c341e54 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Br/BrazilianAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Br/BrazilianAnalyzer.cs
@@ -77,7 +77,7 @@ namespace Lucene.Net.Analysis.Br
/// <summary>
/// Contains words that should be indexed but not stemmed.
/// </summary>
- private CharArraySet excltable = CharArraySet.EMPTY_SET;
+ private CharArraySet excltable = CharArraySet.Empty;
/// <summary>
/// Builds an analyzer with the default stop words (<see cref="DefaultStopSet"/>).
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Ca/CatalanAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Ca/CatalanAnalyzer.cs
index c4f9700ec..d82b84472 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Ca/CatalanAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Ca/CatalanAnalyzer.cs
@@ -93,7 +93,7 @@ namespace Lucene.Net.Analysis.Ca
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public CatalanAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/CharFilter/HTMLStripCharFilter.cs b/src/Lucene.Net.Analysis.Common/Analysis/CharFilter/HTMLStripCharFilter.cs
index 217a76807..efc80ba27 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/CharFilter/HTMLStripCharFilter.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/CharFilter/HTMLStripCharFilter.cs
@@ -30688,13 +30688,13 @@ namespace Lucene.Net.Analysis.CharFilters
{"amp", "AMP" },
};
- private static readonly CharArrayMap<char> entityValues = LoadEntityValues();
+ private static readonly CharArrayDictionary<char> entityValues = LoadEntityValues();
- private static CharArrayMap<char> LoadEntityValues() // LUCENENET: Avoid static constructors (see https://github.com/apache/lucenenet/pull/224#issuecomment-469284006)
+ private static CharArrayDictionary<char> LoadEntityValues() // LUCENENET: Avoid static constructors (see https://github.com/apache/lucenenet/pull/224#issuecomment-469284006)
{
- CharArrayMap<char> entityValues
+ CharArrayDictionary<char> entityValues
#pragma warning disable 612, 618
- = new CharArrayMap<char>(LuceneVersion.LUCENE_CURRENT, 253, false);
+ = new CharArrayDictionary<char>(LuceneVersion.LUCENE_CURRENT, 253, false);
#pragma warning restore 612, 618
string[] entities = {
"AElig", "\u00C6", "Aacute", "\u00C1", "Acirc", "\u00C2",
@@ -30774,10 +30774,10 @@ namespace Lucene.Net.Analysis.CharFilters
for (int i = 0; i < entities.Length; i += 2)
{
var value = entities[i + 1][0];
- entityValues.Put(entities[i], value);
+ entityValues[entities[i]] = value;
if (upperCaseVariantsAccepted.TryGetValue(entities[i], out string upperCaseVariant) && upperCaseVariant != null)
{
- entityValues.Put(upperCaseVariant, value);
+ entityValues[upperCaseVariant] = value;
}
}
return entityValues;
@@ -31611,7 +31611,7 @@ namespace Lucene.Net.Analysis.CharFilters
int length = YyLength;
inputSegment.Write(zzBuffer, zzStartRead, length);
entitySegment.Clear();
- char ch = entityValues.Get(zzBuffer, zzStartRead, length);
+ char ch = entityValues[zzBuffer, zzStartRead, length];
entitySegment.Append(ch);
outputSegment = entitySegment;
YyBegin(CHARACTER_REFERENCE_TAIL);
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Ckb/SoraniAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Ckb/SoraniAnalyzer.cs
index 524e492b4..072c399a4 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Ckb/SoraniAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Ckb/SoraniAnalyzer.cs
@@ -84,7 +84,7 @@ namespace Lucene.Net.Analysis.Ckb
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public SoraniAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Core/StopFilter.cs b/src/Lucene.Net.Analysis.Common/Analysis/Core/StopFilter.cs
index ea4da357f..641a76bf2 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Core/StopFilter.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Core/StopFilter.cs
@@ -1,4 +1,4 @@
-// Lucene version compatibility level 4.8.1
+// Lucene version compatibility level 4.8.1
using Lucene.Net.Analysis.TokenAttributes;
using Lucene.Net.Analysis.Util;
using Lucene.Net.Util;
@@ -115,6 +115,20 @@ namespace Lucene.Net.Analysis.Core
return stopSet;
}
+ /// <summary>
+ /// Creates a stopword set from the given stopword list. </summary>
+ /// <param name="matchVersion"> <see cref="LuceneVersion"/> to enable correct Unicode 4.0 behavior in the returned set if Version > 3.0 </param>
+ /// <param name="stopWords"> A List of <see cref="string"/>s or <see cref="T:char[]"/> or any other ToString()-able list representing the stopwords </param>
+ /// <param name="ignoreCase"> if true, all words are lower cased first </param>
+ /// <returns> A Set (<see cref="CharArraySet"/>) containing the words </returns>
+ // LUCENENET specific - Optimization to go through the string version of UnionWith
+ public static CharArraySet MakeStopSet(LuceneVersion matchVersion, IList<string> stopWords, bool ignoreCase)
+ {
+ var stopSet = new CharArraySet(matchVersion, stopWords.Count, ignoreCase);
+ stopSet.UnionWith(stopWords);
+ return stopSet;
+ }
+
/// <summary>
/// Returns the next input Token whose Term is not a stop word.
/// </summary>
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Cz/CzechAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Cz/CzechAnalyzer.cs
index 169f1261d..0f52bb4e7 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Cz/CzechAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Cz/CzechAnalyzer.cs
@@ -99,7 +99,7 @@ namespace Lucene.Net.Analysis.Cz
/// <param name="matchVersion"> <see cref="LuceneVersion"/> to match </param>
/// <param name="stopwords"> a stopword set </param>
public CzechAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Da/DanishAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Da/DanishAnalyzer.cs
index bb5fdf273..8a41fd86a 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Da/DanishAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Da/DanishAnalyzer.cs
@@ -86,7 +86,7 @@ namespace Lucene.Net.Analysis.Da
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public DanishAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/De/GermanAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/De/GermanAnalyzer.cs
index b88168e62..a3038cd5f 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/De/GermanAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/De/GermanAnalyzer.cs
@@ -137,7 +137,7 @@ namespace Lucene.Net.Analysis.De
/// <param name="stopwords">
/// a stopword set </param>
public GermanAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/En/EnglishAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/En/EnglishAnalyzer.cs
index a163775ca..5975fa42b 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/En/EnglishAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/En/EnglishAnalyzer.cs
@@ -61,7 +61,7 @@ namespace Lucene.Net.Analysis.En
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public EnglishAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/En/KStemmer.cs b/src/Lucene.Net.Analysis.Common/Analysis/En/KStemmer.cs
index 77281f902..f4c395b68 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/En/KStemmer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/En/KStemmer.cs
@@ -339,11 +339,11 @@ namespace Lucene.Net.Analysis.En
}
}
- private static readonly CharArrayMap<DictEntry> dict_ht = InitializeDictHash();
+ private static readonly CharArrayDictionary<DictEntry> dict_ht = InitializeDictHash();
// caching off
//
- // private int maxCacheSize; private CharArrayMap{String} cache =
+ // private int maxCacheSize; private CharArrayDictionary{String} cache =
// null; private static final String SAME = "SAME"; // use if stemmed form is
// the same
@@ -357,7 +357,7 @@ namespace Lucene.Net.Analysis.En
private int k;
// private void initializeStemHash() { if (maxCacheSize > 0) cache = new
- // CharArrayMap<String>(maxCacheSize,false); }
+ // CharArrayDictionary<String>(maxCacheSize,false); }
private char FinalChar => word[k];
@@ -388,20 +388,20 @@ namespace Lucene.Net.Analysis.En
}
}
- private static CharArrayMap<DictEntry> InitializeDictHash()
+ private static CharArrayDictionary<DictEntry> InitializeDictHash()
{
DictEntry defaultEntry;
DictEntry entry;
#pragma warning disable 612, 618
- CharArrayMap<DictEntry> d = new CharArrayMap<DictEntry>(LuceneVersion.LUCENE_CURRENT, 1000, false);
+ CharArrayDictionary<DictEntry> d = new CharArrayDictionary<DictEntry>(LuceneVersion.LUCENE_CURRENT, 1000, false);
#pragma warning restore 612, 618
for (int i = 0; i < exceptionWords.Length; i++)
{
if (!d.ContainsKey(exceptionWords[i]))
{
entry = new DictEntry(exceptionWords[i], true);
- d.Put(exceptionWords[i], entry);
+ d[exceptionWords[i]] = entry;
}
else
{
@@ -414,7 +414,7 @@ namespace Lucene.Net.Analysis.En
if (!d.ContainsKey(directConflations[i][0]))
{
entry = new DictEntry(directConflations[i][1], false);
- d.Put(directConflations[i][0], entry);
+ d[directConflations[i][0]] = entry;
}
else
{
@@ -427,7 +427,7 @@ namespace Lucene.Net.Analysis.En
if (!d.ContainsKey(countryNationality[i][0]))
{
entry = new DictEntry(countryNationality[i][1], false);
- d.Put(countryNationality[i][0], entry);
+ d[countryNationality[i][0]] = entry;
}
else
{
@@ -444,7 +444,7 @@ namespace Lucene.Net.Analysis.En
{
if (!d.ContainsKey(array[i]))
{
- d.Put(array[i], defaultEntry);
+ d[array[i]] = defaultEntry;
}
else
{
@@ -457,7 +457,7 @@ namespace Lucene.Net.Analysis.En
{
if (!d.ContainsKey(array[i]))
{
- d.Put(array[i], defaultEntry);
+ d[array[i]] = defaultEntry;
}
else
{
@@ -470,7 +470,7 @@ namespace Lucene.Net.Analysis.En
{
if (!d.ContainsKey(array[i]))
{
- d.Put(array[i], defaultEntry);
+ d[array[i]] = defaultEntry;
}
else
{
@@ -483,7 +483,7 @@ namespace Lucene.Net.Analysis.En
{
if (!d.ContainsKey(array[i]))
{
- d.Put(array[i], defaultEntry);
+ d[array[i]] = defaultEntry;
}
else
{
@@ -496,7 +496,7 @@ namespace Lucene.Net.Analysis.En
{
if (!d.ContainsKey(array[i]))
{
- d.Put(array[i], defaultEntry);
+ d[array[i]] = defaultEntry;
}
else
{
@@ -509,7 +509,7 @@ namespace Lucene.Net.Analysis.En
{
if (!d.ContainsKey(array[i]))
{
- d.Put(array[i], defaultEntry);
+ d[array[i]] = defaultEntry;
}
else
{
@@ -522,7 +522,7 @@ namespace Lucene.Net.Analysis.En
{
if (!d.ContainsKey(array[i]))
{
- d.Put(array[i], defaultEntry);
+ d[array[i]] = defaultEntry;
}
else
{
@@ -534,7 +534,7 @@ namespace Lucene.Net.Analysis.En
{
if (!d.ContainsKey(KStemData8.data[i]))
{
- d.Put(KStemData8.data[i], defaultEntry);
+ d[KStemData8.data[i]] = defaultEntry;
}
else
{
@@ -546,7 +546,7 @@ namespace Lucene.Net.Analysis.En
{
if (!d.ContainsKey(supplementDict[i]))
{
- d.Put(supplementDict[i], defaultEntry);
+ d[supplementDict[i]] = defaultEntry;
}
else
{
@@ -558,7 +558,7 @@ namespace Lucene.Net.Analysis.En
{
if (!d.ContainsKey(properNouns[i]))
{
- d.Put(properNouns[i], defaultEntry);
+ d[properNouns[i]] = defaultEntry;
}
else
{
@@ -651,8 +651,7 @@ namespace Lucene.Net.Analysis.En
{
return matchedEntry;
}
- DictEntry e = dict_ht.Get(word.Array, 0, word.Length);
- if (e != null && !e.exception)
+ if (dict_ht.TryGetValue(word.Array, 0, word.Length, out DictEntry e) && e != null && !e.exception)
{
matchedEntry = e; // only cache if it's not an exception.
}
@@ -770,8 +769,7 @@ namespace Lucene.Net.Analysis.En
// thisLookup); } else { // System.out.println("new lookup:" + thisLookup);
// }
- matchedEntry = dict_ht.Get(word.Array, 0, word.Length);
- return matchedEntry != null;
+ return dict_ht.TryGetValue(word.Array, 0, word.Length, out matchedEntry) && matchedEntry != null;
}
// Set<String> lookups = new HashSet<>();
@@ -1872,8 +1870,7 @@ namespace Lucene.Net.Analysis.En
// first check the stemmer dictionaries, and avoid using the
// cache if it's in there.
- DictEntry entry = dict_ht.Get(term, 0, len);
- if (entry != null)
+ if (dict_ht.TryGetValue(term, 0, len, out DictEntry entry) && entry != null)
{
if (entry.root != null)
{
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Es/SpanishAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Es/SpanishAnalyzer.cs
index db38db95e..41948c6f6 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Es/SpanishAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Es/SpanishAnalyzer.cs
@@ -94,7 +94,7 @@ namespace Lucene.Net.Analysis.Es
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public SpanishAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Eu/BasqueAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Eu/BasqueAnalyzer.cs
index 3cdf7d084..1e2239992 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Eu/BasqueAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Eu/BasqueAnalyzer.cs
@@ -81,7 +81,7 @@ namespace Lucene.Net.Analysis.Eu
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public BasqueAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Fi/FinnishAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Fi/FinnishAnalyzer.cs
index e445d6c98..874f234e5 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Fi/FinnishAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Fi/FinnishAnalyzer.cs
@@ -86,7 +86,7 @@ namespace Lucene.Net.Analysis.Fi
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public FinnishAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Fr/FrenchAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Fr/FrenchAnalyzer.cs
index 2a95ab789..49ae19ea1 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Fr/FrenchAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Fr/FrenchAnalyzer.cs
@@ -153,7 +153,7 @@ namespace Lucene.Net.Analysis.Fr
/// <param name="stopwords">
/// a stopword set </param>
public FrenchAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Ga/IrishAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Ga/IrishAnalyzer.cs
index b4e572c20..87c4c585b 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Ga/IrishAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Ga/IrishAnalyzer.cs
@@ -98,7 +98,7 @@ namespace Lucene.Net.Analysis.Ga
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public IrishAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Gl/GalicianAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Gl/GalicianAnalyzer.cs
index 87e6f1d49..5c38ab5ac 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Gl/GalicianAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Gl/GalicianAnalyzer.cs
@@ -84,7 +84,7 @@ namespace Lucene.Net.Analysis.Gl
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public GalicianAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Hi/HindiAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Hi/HindiAnalyzer.cs
index 828b4faa6..c4ed75f09 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Hi/HindiAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Hi/HindiAnalyzer.cs
@@ -95,7 +95,7 @@ namespace Lucene.Net.Analysis.Hi
/// <param name="version"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public HindiAnalyzer(LuceneVersion version, CharArraySet stopwords)
- : this(version, stopwords, CharArraySet.EMPTY_SET)
+ : this(version, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Hu/HungarianAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Hu/HungarianAnalyzer.cs
index 557d6666a..b8cdeb5fa 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Hu/HungarianAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Hu/HungarianAnalyzer.cs
@@ -87,7 +87,7 @@ namespace Lucene.Net.Analysis.Hu
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public HungarianAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Hunspell/Stemmer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Hunspell/Stemmer.cs
index 520e57481..e15e6365c 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Hunspell/Stemmer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Hunspell/Stemmer.cs
@@ -1,5 +1,6 @@
// Lucene version compatibility level 4.10.4
using J2N.Numerics;
+using J2N.Text;
using Lucene.Net.Analysis.Util;
using Lucene.Net.Diagnostics;
using Lucene.Net.Store;
@@ -253,10 +254,10 @@ namespace Lucene.Net.Analysis.Hunspell
IList<CharsRef> deduped = new JCG.List<CharsRef>();
foreach (CharsRef s in stems)
{
- if (!terms.Contains(s))
+ if (!terms.Contains((ICharSequence)s)) // LUCENENET: Cast to get to ICharSequence overload
{
deduped.Add(s);
- terms.Add(s);
+ terms.Add((ICharSequence)s); // LUCENENET: Cast to get to ICharSequence overload
}
}
return deduped;
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Hy/ArmenianAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Hy/ArmenianAnalyzer.cs
index aff5eec13..e92f9a32a 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Hy/ArmenianAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Hy/ArmenianAnalyzer.cs
@@ -82,7 +82,7 @@ namespace Lucene.Net.Analysis.Hy
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public ArmenianAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Id/IndonesianAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Id/IndonesianAnalyzer.cs
index 8d761c858..0fa5129a4 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Id/IndonesianAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Id/IndonesianAnalyzer.cs
@@ -81,7 +81,7 @@ namespace Lucene.Net.Analysis.Id
/// <param name="stopwords">
/// a stopword set </param>
public IndonesianAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/It/ItalianAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/It/ItalianAnalyzer.cs
index 659d4098d..e3f19783e 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/It/ItalianAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/It/ItalianAnalyzer.cs
@@ -102,7 +102,7 @@ namespace Lucene.Net.Analysis.It
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public ItalianAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Lv/LatvianAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Lv/LatvianAnalyzer.cs
index c9c152c32..75904c9aa 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Lv/LatvianAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Lv/LatvianAnalyzer.cs
@@ -85,7 +85,7 @@ namespace Lucene.Net.Analysis.Lv
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public LatvianAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Nl/DutchAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Nl/DutchAnalyzer.cs
index 08579e941..396bd7cab 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Nl/DutchAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Nl/DutchAnalyzer.cs
@@ -70,7 +70,7 @@ namespace Lucene.Net.Analysis.Nl
private static class DefaultSetHolder
{
internal static readonly CharArraySet DEFAULT_STOP_SET = LoadDefaultStopSet();
- internal static readonly CharArrayMap<string> DEFAULT_STEM_DICT = LoadDefaultStemDict();
+ internal static readonly CharArrayDictionary<string> DEFAULT_STEM_DICT = LoadDefaultStemDict();
private static CharArraySet LoadDefaultStopSet() // LUCENENET: Avoid static constructors (see https://github.com/apache/lucenenet/pull/224#issuecomment-469284006)
{
try
@@ -90,15 +90,15 @@ namespace Lucene.Net.Analysis.Nl
}
- private static CharArrayMap<string> LoadDefaultStemDict() // LUCENENET: Avoid static constructors (see https://github.com/apache/lucenenet/pull/224#issuecomment-469284006)
+ private static CharArrayDictionary<string> LoadDefaultStemDict() // LUCENENET: Avoid static constructors (see https://github.com/apache/lucenenet/pull/224#issuecomment-469284006)
{
#pragma warning disable 612, 618
- var DEFAULT_STEM_DICT = new CharArrayMap<string>(LuceneVersion.LUCENE_CURRENT, 4, false);
+ var DEFAULT_STEM_DICT = new CharArrayDictionary<string>(LuceneVersion.LUCENE_CURRENT, 4, false);
#pragma warning restore 612, 618
- DEFAULT_STEM_DICT.Put("fiets", "fiets"); //otherwise fiet
- DEFAULT_STEM_DICT.Put("bromfiets", "bromfiets"); //otherwise bromfiet
- DEFAULT_STEM_DICT.Put("ei", "eier");
- DEFAULT_STEM_DICT.Put("kind", "kinder");
+ DEFAULT_STEM_DICT["fiets"] = "fiets"; //otherwise fiet
+ DEFAULT_STEM_DICT["bromfiets"] = "bromfiets"; //otherwise bromfiet
+ DEFAULT_STEM_DICT["ei"] = "eier";
+ DEFAULT_STEM_DICT["kind"] = "kinder";
return DEFAULT_STEM_DICT;
}
}
@@ -112,12 +112,12 @@ namespace Lucene.Net.Analysis.Nl
/// <summary>
/// Contains words that should be indexed but not stemmed.
/// </summary>
- private CharArraySet excltable = CharArraySet.EMPTY_SET;
+ private CharArraySet excltable = CharArraySet.Empty;
private readonly StemmerOverrideFilter.StemmerOverrideMap stemdict;
// null if on 3.1 or later - only for bw compat
- private readonly CharArrayMap<string> origStemdict;
+ private readonly CharArrayDictionary<string> origStemdict;
private readonly LuceneVersion matchVersion;
/// <summary>
@@ -125,17 +125,17 @@ namespace Lucene.Net.Analysis.Nl
/// and a few default entries for the stem exclusion table.
/// </summary>
public DutchAnalyzer(LuceneVersion matchVersion)
- : this(matchVersion, DefaultSetHolder.DEFAULT_STOP_SET, CharArraySet.EMPTY_SET, DefaultSetHolder.DEFAULT_STEM_DICT)
+ : this(matchVersion, DefaultSetHolder.DEFAULT_STOP_SET, CharArraySet.Empty, DefaultSetHolder.DEFAULT_STEM_DICT)
{
// historically, only this ctor populated the stem dict!!!!!
}
public DutchAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET,
+ : this(matchVersion, stopwords, CharArraySet.Empty,
#pragma warning disable 612, 618
matchVersion.OnOrAfter(LuceneVersion.LUCENE_36) ?
#pragma warning restore 612, 618
- DefaultSetHolder.DEFAULT_STEM_DICT : CharArrayMap<string>.EmptyMap())
+ DefaultSetHolder.DEFAULT_STEM_DICT : CharArrayDictionary<string>.Empty)
{
// historically, this ctor never the stem dict!!!!!
// so we populate it only for >= 3.6
@@ -146,13 +146,13 @@ namespace Lucene.Net.Analysis.Nl
#pragma warning disable 612, 618
matchVersion.OnOrAfter(LuceneVersion.LUCENE_36) ?
#pragma warning restore 612, 618
- DefaultSetHolder.DEFAULT_STEM_DICT : CharArrayMap<string>.EmptyMap())
+ DefaultSetHolder.DEFAULT_STEM_DICT : CharArrayDictionary<string>.Empty)
{
// historically, this ctor never the stem dict!!!!!
// so we populate it only for >= 3.6
}
- public DutchAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords, CharArraySet stemExclusionTable, CharArrayMap<string> stemOverrideDict)
+ public DutchAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords, CharArraySet stemExclusionTable, CharArrayDictionary<string> stemOverrideDict)
{
this.matchVersion = matchVersion;
this.stoptable = CharArraySet.Copy(matchVersion, stopwords).AsReadOnly();
@@ -162,19 +162,19 @@ namespace Lucene.Net.Analysis.Nl
#pragma warning restore 612, 618
{
this.stemdict = null;
- this.origStemdict = CharArrayMap.Copy(matchVersion, stemOverrideDict).AsReadOnly();
+ this.origStemdict = CharArrayDictionary.Copy(matchVersion, stemOverrideDict).AsReadOnly();
}
else
{
this.origStemdict = null;
// we don't need to ignore case here since we lowercase in this analyzer anyway
StemmerOverrideFilter.Builder builder = new StemmerOverrideFilter.Builder(false);
- using (CharArrayMap<string>.EntryIterator iter = (CharArrayMap<string>.EntryIterator)stemOverrideDict.EntrySet().GetEnumerator())
+ using (var iter = stemOverrideDict.GetEnumerator())
{
CharsRef spare = new CharsRef();
- while (iter.HasNext)
+ while (iter.MoveNext())
{
- char[] nextKey = iter.NextKey();
+ char[] nextKey = iter.CurrentKey;
spare.CopyChars(nextKey, 0, nextKey.Length);
builder.Add(spare.Chars, iter.CurrentValue);
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Nl/DutchStemFilter.cs b/src/Lucene.Net.Analysis.Common/Analysis/Nl/DutchStemFilter.cs
index 500e64003..27404c072 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Nl/DutchStemFilter.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Nl/DutchStemFilter.cs
@@ -113,13 +113,13 @@ namespace Lucene.Net.Analysis.Nl
/// Set dictionary for stemming, this dictionary overrules the algorithm,
/// so you can correct for a particular unwanted word-stem pair.
/// </summary>
- public CharArrayMap<string> StemDictionary
+ public CharArrayDictionary<string> StemDictionary
{
get // LUCENENET NOTE: Added getter per MSDN guidelines
{
if (stemmer != null)
{
- return stemmer.StemDictionary as CharArrayMap<string>;
+ return stemmer.StemDictionary as CharArrayDictionary<string>;
}
return null;
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/No/NorwegianAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/No/NorwegianAnalyzer.cs
index 499457e03..7e7c264b5 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/No/NorwegianAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/No/NorwegianAnalyzer.cs
@@ -86,7 +86,7 @@ namespace Lucene.Net.Analysis.No
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public NorwegianAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Pt/PortugueseAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Pt/PortugueseAnalyzer.cs
index 307e3be48..2eb343920 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Pt/PortugueseAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Pt/PortugueseAnalyzer.cs
@@ -91,7 +91,7 @@ namespace Lucene.Net.Analysis.Pt
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public PortugueseAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Ro/RomanianAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Ro/RomanianAnalyzer.cs
index 929ae73bf..6d78f9fb5 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Ro/RomanianAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Ro/RomanianAnalyzer.cs
@@ -87,7 +87,7 @@ namespace Lucene.Net.Analysis.Ro
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public RomanianAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Ru/RussianAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Ru/RussianAnalyzer.cs
index d7fd7575c..5af5f5a13 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Ru/RussianAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Ru/RussianAnalyzer.cs
@@ -116,7 +116,7 @@ namespace Lucene.Net.Analysis.Ru
/// <param name="stopwords">
/// a stopword set </param>
public RussianAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Sv/SwedishAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Sv/SwedishAnalyzer.cs
index 6c12d5e94..a7254d96b 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Sv/SwedishAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Sv/SwedishAnalyzer.cs
@@ -87,7 +87,7 @@ namespace Lucene.Net.Analysis.Sv
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public SwedishAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Synonym/SlowSynonymFilter.cs b/src/Lucene.Net.Analysis.Common/Analysis/Synonym/SlowSynonymFilter.cs
index 94ebfeee9..79ab12d43 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Synonym/SlowSynonymFilter.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Synonym/SlowSynonymFilter.cs
@@ -95,8 +95,7 @@ namespace Lucene.Net.Analysis.Synonym
return false;
}
var termAtt = firstTok.AddAttribute<ICharTermAttribute>();
- SlowSynonymMap result = map.Submap != null ? map.Submap.Get(termAtt.Buffer, 0, termAtt.Length) : null;
- if (result is null)
+ if (map.Submap is null || !map.Submap.TryGetValue(termAtt.Buffer, 0, termAtt.Length, out SlowSynonymMap result) || result is null)
{
Copy(this, firstTok);
return true;
@@ -274,9 +273,8 @@ namespace Lucene.Net.Analysis.Synonym
}
// check for positionIncrement!=1? if>1, should not match, if==0, check multiple at this level?
var termAtt = tok.GetAttribute<ICharTermAttribute>();
- SlowSynonymMap subMap = map.Submap.Get(termAtt.Buffer, 0, termAtt.Length);
- if (subMap != null)
+ if (map.Submap.TryGetValue(termAtt.Buffer, 0, termAtt.Length, out SlowSynonymMap subMap) && subMap != null)
{
// recurse
result = Match(subMap);
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Synonym/SlowSynonymMap.cs b/src/Lucene.Net.Analysis.Common/Analysis/Synonym/SlowSynonymMap.cs
index 875385bf0..8e774ada4 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Synonym/SlowSynonymMap.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Synonym/SlowSynonymMap.cs
@@ -37,12 +37,12 @@ namespace Lucene.Net.Analysis.Synonym
{
/// <summary>
/// @lucene.internal </summary>
- public CharArrayMap<SlowSynonymMap> Submap // recursive: Map<String, SynonymMap>
+ public CharArrayDictionary<SlowSynonymMap> Submap // recursive: Map<String, SynonymMap>
{
get => submap;
set => submap = value;
}
- private CharArrayMap<SlowSynonymMap> submap;
+ private CharArrayDictionary<SlowSynonymMap> submap;
/// <summary>
/// @lucene.internal </summary>
@@ -88,15 +88,14 @@ namespace Lucene.Net.Analysis.Synonym
{
// for now hardcode at 4.0, as its what the old code did.
// would be nice to fix, but shouldn't store a version in each submap!!!
- currMap.submap = new CharArrayMap<SlowSynonymMap>(LuceneVersion.LUCENE_CURRENT, 1, IgnoreCase);
+ currMap.submap = new CharArrayDictionary<SlowSynonymMap>(LuceneVersion.LUCENE_CURRENT, 1, IgnoreCase);
}
- var map = currMap.submap.Get(str);
- if (map is null)
+ if (!currMap.submap.TryGetValue(str, out SlowSynonymMap map) || map is null)
{
map = new SlowSynonymMap();
map.flags |= flags & IGNORE_CASE;
- currMap.submap.Put(str, map);
+ currMap.submap[str] = map;
}
currMap = map;
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Tr/TurkishAnalyzer.cs b/src/Lucene.Net.Analysis.Common/Analysis/Tr/TurkishAnalyzer.cs
index 6e6c48c30..9a56850bf 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Tr/TurkishAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Tr/TurkishAnalyzer.cs
@@ -86,7 +86,7 @@ namespace Lucene.Net.Analysis.Tr
/// <param name="matchVersion"> lucene compatibility version </param>
/// <param name="stopwords"> a stopword set </param>
public TurkishAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs b/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs
index db0e30c11..050da6771 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs
@@ -3,13 +3,19 @@ using J2N;
using J2N.Globalization;
using J2N.Text;
using Lucene.Net.Diagnostics;
+using Lucene.Net.Support;
using Lucene.Net.Util;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
+using System.Runtime.CompilerServices;
using System.Text;
+using JCG = J2N.Collections.Generic;
+#nullable enable
namespace Lucene.Net.Analysis.Util
{
@@ -31,17 +37,17 @@ namespace Lucene.Net.Analysis.Util
*/
/// <summary>
- /// A simple class that stores key <see cref="string"/>s as <see cref="T:char[]"/>'s in a
+ /// A simple class that stores text <see cref="string"/>s as <see cref="T: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,
+ /// dictionary, nor does it resize its hash table to be smaller,
/// etc. It is designed to be quick to retrieve items
/// by <see cref="T:char[]"/> keys without the necessity of converting
/// to a <see cref="string"/> first.
///
/// <a name="version"></a>
/// <para>You must specify the required <see cref="LuceneVersion"/>
- /// compatibility when creating <see cref="CharArrayMap"/>:
+ /// compatibility when creating <see cref="CharArrayDictionary{TValue}"/>:
/// <list type="bullet">
/// <item><description> As of 3.1, supplementary characters are
/// properly lowercased.</description></item>
@@ -49,14 +55,17 @@ namespace Lucene.Net.Analysis.Util
/// 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
- /// <see cref="CharArrayMap"/> with the behavior before Lucene
+ /// <see cref="CharArrayDictionary{TValue}"/> with the behavior before Lucene
/// 3.1 pass a <see cref="LuceneVersion"/> < 3.1 to the constructors.
/// </para>
/// </summary>
- public class CharArrayMap<TValue> : ICharArrayMap, IDictionary<string, TValue>
+ [DebuggerDisplay("Count = {Count}, Values = {ToString()}")]
+ public class CharArrayDictionary<TValue> : ICharArrayDictionary, IDictionary<string, TValue>, IDictionary, IReadOnlyDictionary<string, TValue>
{
- // private only because missing generics
- private static readonly CharArrayMap<TValue> EMPTY_MAP = new CharArrayMap.EmptyCharArrayMap<TValue>();
+ // LUCENENET: Made public, renamed Empty
+ /// <summary>
+ /// Returns an empty, read-only dictionary. </summary>
+ public static readonly CharArrayDictionary<TValue> Empty = new CharArrayDictionary.EmptyCharArrayDictionary<TValue>();
private const int INIT_SIZE = 8;
private readonly CharacterUtils charUtils;
@@ -66,11 +75,15 @@ namespace Lucene.Net.Analysis.Util
internal char[][] keys; // package private because used in CharArraySet's non Set-conform CharArraySetIterator
internal MapValue[] values; // package private because used in CharArraySet's non Set-conform CharArraySetIterator
+ private int version; // LUCENENET specific - protection so mutating the state of the collection causes enumerators to throw exceptions.
+
/// <summary>
- /// LUCENENET: Moved this from CharArraySet so it doesn't need to know the generic type of CharArrayMap
+ /// LUCENENET: Moved this from CharArraySet so it doesn't need to know the generic type of CharArrayDictionary
/// </summary>
internal static readonly MapValue PLACEHOLDER = new MapValue();
+ bool ICharArrayDictionary.IgnoreCase => ignoreCase;
+
/// <summary>
/// LUCENENET SPECIFIC type used to act as a placeholder. Since <c>null</c>
/// means that our value is not populated, we need an instance of something
@@ -87,37 +100,45 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
internal class MapValue
{
+ [AllowNull]
private TValue value = default;
+
+ [AllowNull]
public TValue Value
{
- get => value;
+ get => value!; // We are lying here - if this is a reference type, it could be null. But we don't care because IDictionary<TKey, TValue> doesn't care.
set => this.value = value;
}
public MapValue()
{ }
- public MapValue(TValue value)
+ public MapValue([AllowNull] TValue value)
{
this.value = value;
}
}
/// <summary>
- /// Create map with enough capacity to hold <paramref name="startSize"/> terms
+ /// Create dictionary with enough capacity to hold <paramref name="capacity"/> terms.
/// </summary>
/// <param name="matchVersion">
- /// lucene compatibility version - see <see cref="CharArrayMap{TValue}"/> for details. </param>
- /// <param name="startSize">
+ /// lucene compatibility version - see <see cref="CharArrayDictionary{TValue}"/> for details. </param>
+ /// <param name="capacity">
/// the initial capacity </param>
/// <param name="ignoreCase">
/// <c>false</c> if and only if the set should be case sensitive;
/// otherwise <c>true</c>. </param>
- public CharArrayMap(LuceneVersion matchVersion, int startSize, bool ignoreCase)
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is less than zero.</exception>
+ public CharArrayDictionary(LuceneVersion matchVersion, int capacity, bool ignoreCase)
{
+ // LUCENENET: Added guard clause
+ if (capacity < 0)
+ throw new ArgumentOutOfRangeException(nameof(capacity), SR.ArgumentOutOfRange_NeedNonNegNum);
+
this.ignoreCase = ignoreCase;
var size = INIT_SIZE;
- while (startSize + (startSize >> 2) > size)
+ while (capacity + (capacity >> 2) > size)
{
size <<= 1;
}
@@ -128,29 +149,96 @@ namespace Lucene.Net.Analysis.Util
}
/// <summary>
- /// Creates a map from the mappings in another map.
+ /// Creates a dictionary from the mappings in another dictionary.
/// </summary>
/// <param name="matchVersion">
- /// compatibility match version see <a href="#version">Version
- /// note</a> above for details. </param>
- /// <param name="c">
- /// a map (<see cref="T:IDictionary{string, V}"/>) whose mappings to be copied </param>
+ /// compatibility match version see <see cref="CharArrayDictionary{TValue}"/> for details. </param>
+ /// <param name="collection">
+ /// a dictionary (<see cref="T:IDictionary{string, V}"/>) whose mappings to be copied. </param>
+ /// <param name="ignoreCase">
+ /// <c>false</c> if and only if the set should be case sensitive;
+ /// otherwise <c>true</c>. </param>
+ /// <exception cref="ArgumentNullException"><paramref name="collection"/> is <c>null</c>.</exception>
+ public CharArrayDictionary(LuceneVersion matchVersion, IDictionary<string, TValue> collection, bool ignoreCase)
+ : this(matchVersion, collection?.Count ?? 0, ignoreCase)
+ {
+ // LUCENENET: Added guard clause
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ foreach (var v in collection)
+ {
+ // LUCENENET: S1699: Don't call call protected members in the constructor
+ if (keys[GetSlot(v.Key)] != null) // ContainsKey
+ {
+ throw new ArgumentException(string.Format(SR.Argument_AddingDuplicate, v.Key));
+ }
+ SetImpl(v.Key, new MapValue(v.Value));
+ }
+ }
+
+ /// <summary>
+ /// Creates a dictionary from the mappings in another dictionary.
+ /// </summary>
+ /// <param name="matchVersion">
+ /// compatibility match version see <see cref="CharArrayDictionary{TValue}"/> for details. </param>
+ /// <param name="collection">
+ /// a dictionary (<see cref="T:IDictionary{char[], V}"/>) whose mappings to be copied. </param>
+ /// <param name="ignoreCase">
+ /// <c>false</c> if and only if the set should be case sensitive;
+ /// otherwise <c>true</c>. </param>
+ /// <exception cref="ArgumentNullException"><paramref name="collection"/> is <c>null</c>.</exception>
+ public CharArrayDictionary(LuceneVersion matchVersion, IDictionary<char[], TValue> collection, bool ignoreCase)
+ : this(matchVersion, collection?.Count ?? 0, ignoreCase)
+ {
+ // LUCENENET: Added guard clause
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ foreach (var v in collection)
+ {
+ // LUCENENET: S1699: Don't call call protected members in the constructor
+ if (keys[GetSlot(v.Key!, 0, v.Key?.Length ?? 0)] != null) // ContainsKey
+ {
+ throw new ArgumentException(string.Format(SR.Argument_AddingDuplicate, v.Key));
+ }
+ SetImpl(v.Key!, new MapValue(v.Value));
+ }
+ }
+
+ /// <summary>
+ /// Creates a dictionary from the mappings in another dictionary.
+ /// </summary>
+ /// <param name="matchVersion">
+ /// compatibility match version see <see cref="CharArrayDictionary{TValue}"/> for details. </param>
+ /// <param name="collection">
+ /// a dictionary (<see cref="T:IDictionary{ICharSequence, V}"/>) whose mappings to be copied. </param>
/// <param name="ignoreCase">
/// <c>false</c> if and only if the set should be case sensitive;
/// otherwise <c>true</c>. </param>
- public CharArrayMap(LuceneVersion matchVersion, IDictionary<string, TValue> c, bool ignoreCase)
- : this(matchVersion, c.Count, ignoreCase)
+ /// <exception cref="ArgumentNullException"><paramref name="collection"/> is <c>null</c>.</exception>
+ public CharArrayDictionary(LuceneVersion matchVersion, IDictionary<ICharSequence, TValue> collection, bool ignoreCase)
+ : this(matchVersion, collection?.Count ?? 0, ignoreCase)
{
- foreach (var v in c)
+ // LUCENENET: Added guard clause
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ foreach (var v in collection)
{
- Add(v);
+ // LUCENENET: S1699: Don't call call protected members in the constructor
+ if (keys[GetSlot(v.Key)] != null) // ContainsKey
+ {
+ throw new ArgumentException(string.Format(SR.Argument_AddingDuplicate, v.Key));
+ }
+ SetImpl(v.Key, new MapValue(v.Value));
}
}
/// <summary>
- /// Create set from the supplied map (used internally for readonly maps...)
+ /// Create set from the supplied dictionary (used internally for readonly maps...)
/// </summary>
- internal CharArrayMap(CharArrayMap<TValue> toCopy)
+ internal CharArrayDictionary(CharArrayDictionary<TValue> toCopy)
{
this.keys = toCopy.keys;
this.values = toCopy.values;
@@ -166,97 +254,205 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
/// <param name="item">A <see cref="T:KeyValuePair{string, V}"/> whose <see cref="T:KeyValuePair{string, V}.Value"/>
/// will be added for the corresponding <see cref="T:KeyValuePair{string, V}.Key"/>. </param>
- public virtual void Add(KeyValuePair<string, TValue> item)
+ void ICollection<KeyValuePair<string, TValue>>.Add(KeyValuePair<string, TValue> item)
{
Add(item.Key, item.Value);
}
/// <summary>
- /// Adds the <paramref name="value"/> for the passed in <paramref name="key"/>.
+ /// Adds the <paramref name="value"/> for the passed in <paramref name="text"/>.
+ /// </summary>
+ /// <param name="text">The string-able type to be added/updated in the dictionary.</param>
+ /// <param name="value">The corresponding value for the given <paramref name="text"/>.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentException">An element with <paramref name="text"/> already exists in the dictionary.</exception>
+ public virtual void Add(string text, TValue value)
+ {
+ if (ContainsKey(text))
+ {
+ throw new ArgumentException(string.Format(SR.Argument_AddingDuplicate, text), nameof(text));
+ }
+ Set(text, value);
+ }
+
+ /// <summary>
+ /// Adds the <paramref name="value"/> for the passed in <paramref name="text"/>.
+ /// </summary>
+ /// <param name="text">The string-able type to be added/updated in the dictionary.</param>
+ /// <param name="value">The corresponding value for the given <paramref name="text"/>.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentException">An element with <paramref name="text"/> already exists in the dictionary.</exception>
+ public virtual void Add(char[] text, TValue value)
+ {
+ if (ContainsKey(text))
+ {
+ throw new ArgumentException(string.Format(SR.Argument_AddingDuplicate, text), nameof(text));
+ }
+ Set(text, value);
+ }
+
+ /// <summary>
+ /// Adds the <paramref name="value"/> for the passed in <paramref name="text"/>.
+ /// </summary>
+ /// <param name="text">The string-able type to be added/updated in the dictionary.</param>
+ /// <param name="value">The corresponding value for the given <paramref name="text"/>.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="text"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <paramref name="text"/>'s <see cref="ICharSequence.HasValue"/> property returns <c>false</c>.
+ /// </exception>
+ /// <exception cref="ArgumentException">An element with <paramref name="text"/> already exists in the dictionary.</exception>
+ public virtual void Add(ICharSequence text, TValue value)
+ {
+ if (ContainsKey(text))
+ {
+ throw new ArgumentException(string.Format(SR.Argument_AddingDuplicate, text), nameof(text));
+ }
+ Set(text, value);
+ }
+
+ /// <summary>
+ /// Adds the <paramref name="value"/> for the passed in <paramref name="text"/>.
/// </summary>
- /// <param name="key">The string-able type to be added/updated in the dictionary.</param>
- /// <param name="value">The corresponding value for the given <paramref name="key"/>.</param>
- public virtual void Add(string key, TValue value)
+ /// <param name="text">The string-able type to be added/updated in the dictionary.</param>
+ /// <param name="value">The corresponding value for the given <paramref name="text"/>.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentException">An element with <paramref name="text"/> already exists in the dictionary.</exception>
+ public virtual void Add<T>(T text, TValue value)
{
- if (ContainsKey(key))
+ if (ContainsKey(text))
{
- throw new ArgumentException("The key " + key + " already exists in the dictionary");
+ throw new ArgumentException(string.Format(SR.Argument_AddingDuplicate, text), nameof(text));
}
- Put(key, value);
+ Set(text, value);
}
/// <summary>
- /// Returns an unmodifiable <see cref="CharArrayMap{TValue}"/>. This allows to provide
- /// unmodifiable views of internal map for "read-only" use.
+ /// Returns an unmodifiable <see cref="CharArrayDictionary{TValue}"/>. This allows to provide
+ /// unmodifiable views of internal dictionary for "read-only" use.
/// </summary>
- /// <returns> an new unmodifiable <see cref="CharArrayMap{TValue}"/>. </returns>
+ /// <returns> an new unmodifiable <see cref="CharArrayDictionary{TValue}"/>. </returns>
// LUCENENET specific - allow .NET-like syntax for creating immutable collections
- public CharArrayMap<TValue> AsReadOnly()
+ public CharArrayDictionary<TValue> AsReadOnly()
{
- return this is CharArrayMap.UnmodifiableCharArrayMap<TValue> readOnlyDictionary ?
+ return this is CharArrayDictionary.ReadOnlyCharArrayDictionary<TValue> readOnlyDictionary ?
readOnlyDictionary :
- new CharArrayMap.UnmodifiableCharArrayMap<TValue>(this);
+ new CharArrayDictionary.ReadOnlyCharArrayDictionary<TValue>(this);
}
/// <summary>
- /// Clears all entries in this map. This method is supported for reusing, but not
+ /// Clears all entries in this dictionary. This method is supported for reusing, but not
/// <see cref="IDictionary{TKey, TValue}.Remove(TKey)"/>.
/// </summary>
public virtual void Clear()
{
+ version++;
count = 0;
keys.Fill(null);
values.Fill(null);
}
/// <summary>
- /// Not supported.
+ /// Not supported.
/// </summary>
- [Obsolete("Not applicable in this class.")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
- public virtual bool Contains(KeyValuePair<string, TValue> item) // LUCENENET TODO: API - rather than marking this DesignerSerializationVisibility.Hidden, it would be better to make an explicit implementation that isn't public
+ bool ICollection<KeyValuePair<string, TValue>>.Contains(KeyValuePair<string, TValue> item)
{
throw UnsupportedOperationException.Create();
}
/// <summary>
- /// Copies all items in the current dictionary the <paramref name="array"/> starting at the <paramref name="arrayIndex"/>.
+ /// Copies all items in the current dictionary the <paramref name="array"/> starting at the <paramref name="index"/>.
+ /// The array is assumed to already be dimensioned to fit the elements in this dictionary; otherwise a <see cref="ArgumentOutOfRangeException"/>
+ /// will be thrown.
+ /// </summary>
+ /// <param name="array">The array to copy the items into.</param>
+ /// <param name="index">A 32-bit integer that represents the index in <paramref name="array"/> at which copying begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException">The number of elements in the source is greater
+ /// than the available space from <paramref name="index"/> to the end of the destination array.</exception>
+ public virtual void CopyTo(KeyValuePair<string, TValue>[] array, int index)
+ {
+ if (array is null)
+ throw new ArgumentNullException(nameof(array));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (count > array.Length - index)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+
+ using var iter = GetEnumerator();
+ for (int i = index; iter.MoveNext(); i++)
+ {
+ array[i] = new KeyValuePair<string, TValue>(iter.CurrentKeyString, iter.CurrentValue!);
+ }
+ }
+
+ /// <summary>
+ /// Copies all items in the current dictionary the <paramref name="array"/> starting at the <paramref name="index"/>.
/// The array is assumed to already be dimensioned to fit the elements in this dictionary; otherwise a <see cref="ArgumentOutOfRangeException"/>
/// will be thrown.
/// </summary>
/// <param name="array">The array to copy the items into.</param>
- /// <param name="arrayIndex">A 32-bit integer that represents the index in <paramref name="array"/> at which copying begins.</param>
- public virtual void CopyTo(KeyValuePair<string, TValue>[] array, int arrayIndex)
+ /// <param name="index">A 32-bit integer that represents the index in <paramref name="array"/> at which copying begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException">The number of elements in the source is greater
+ /// than the available space from <paramref name="index"/> to the end of the destination array.</exception>
+ public virtual void CopyTo(KeyValuePair<char[], TValue>[] array, int index)
{
- using var iter = (EntryIterator)EntrySet().GetEnumerator();
- for (int i = arrayIndex; iter.MoveNext(); i++)
+ if (array is null)
+ throw new ArgumentNullException(nameof(array));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (count > array.Length - index)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+
+ using var iter = GetEnumerator();
+ for (int i = index; iter.MoveNext(); i++)
{
- array[i] = new KeyValuePair<string, TValue>(iter.Current.Key, iter.CurrentValue);
+ array[i] = new KeyValuePair<char[], TValue>((char[])iter.CurrentKey.Clone(), iter.CurrentValue!);
}
}
/// <summary>
- /// Copies all items in the current <see cref="CharArrayMap{TValue}"/> to the passed in
- /// <see cref="CharArrayMap{TValue}"/>.
+ /// Copies all items in the current dictionary the <paramref name="array"/> starting at the <paramref name="index"/>.
+ /// The array is assumed to already be dimensioned to fit the elements in this dictionary; otherwise a <see cref="ArgumentOutOfRangeException"/>
+ /// will be thrown.
/// </summary>
- /// <param name="map"></param>
- public virtual void CopyTo(CharArrayMap<TValue> map)
+ /// <param name="array">The array to copy the items into.</param>
+ /// <param name="index">A 32-bit integer that represents the index in <paramref name="array"/> at which copying begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException">The number of elements in the source is greater
+ /// than the available space from <paramref name="index"/> to the end of the destination array.</exception>
+ public virtual void CopyTo(KeyValuePair<ICharSequence, TValue>[] array, int index)
{
- using var iter = (EntryIterator)EntrySet().GetEnumerator();
- while (iter.MoveNext())
+ if (array is null)
+ throw new ArgumentNullException(nameof(array));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (count > array.Length - index)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+
+ using var iter = GetEnumerator();
+ for (int i = index; iter.MoveNext(); i++)
{
- map.Put(iter.Current.Key, iter.CurrentValue);
+ array[i] = new KeyValuePair<ICharSequence, TValue>(((char[])iter.CurrentKey.Clone()).AsCharSequence(), iter.CurrentValue!);
}
}
/// <summary>
- /// <c>true</c> if the <paramref name="length"/> chars of <paramref name="text"/> starting at <paramref name="offset"/>
+ /// <c>true</c> if the <paramref name="length"/> chars of <paramref name="text"/> starting at <paramref name="startIndex"/>
/// are in the <see cref="Keys"/>
/// </summary>
- public virtual bool ContainsKey(char[] text, int offset, int length)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref name="length"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="startIndex"/> and <paramref name="length"/> refer to a position outside of <paramref name="text"/>.</exception>
+ public virtual bool ContainsKey(char[] text, int startIndex, int length)
{
- return keys[GetSlot(text, offset, length)] != null;
+ return keys[GetSlot(text, startIndex, length)] != null;
}
/// <summary>
@@ -264,8 +460,12 @@ namespace Lucene.Net.Analysis.Util
/// <paramref name="text"/> <see cref="T:char[]"/> being passed in;
/// otherwise <c>false</c>.
/// </summary>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
public virtual bool ContainsKey(char[] text)
{
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
return keys[GetSlot(text, 0, text.Length)] != null;
}
@@ -273,6 +473,7 @@ namespace Lucene.Net.Analysis.Util
/// <c>true</c> if the <paramref name="text"/> <see cref="string"/> is in the <see cref="Keys"/>;
/// otherwise <c>false</c>
/// </summary>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
public virtual bool ContainsKey(string text)
{
return keys[GetSlot(text)] != null;
@@ -282,91 +483,180 @@ namespace Lucene.Net.Analysis.Util
/// <c>true</c> if the <paramref name="text"/> <see cref="ICharSequence"/> is in the <see cref="Keys"/>;
/// otherwise <c>false</c>
/// </summary>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="text"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <paramref name="text"/>'s <see cref="ICharSequence.HasValue"/> property returns <c>false</c>.
+ /// </exception>
public virtual bool ContainsKey(ICharSequence text)
{
+ if (text is null || !text.HasValue)
+ throw new ArgumentNullException(nameof(text));
+
+ if (text is CharArrayCharSequence charArrayCs)
+ return ContainsKey(charArrayCs.Value!);
+ if (text is StringBuilderCharSequence stringBuilderCs)
+ return ContainsKey(stringBuilderCs.Value!.ToString()); // LUCENENET: Indexing into a StringBuilder is slow, so materialize
+
return keys[GetSlot(text)] != null;
}
/// <summary>
- /// <c>true</c> if the <paramref name="o"/> <see cref="object.ToString()"/> is in the <see cref="Keys"/>;
- /// otherwise <c>false</c>
+ /// <c>true</c> if the <paramref name="text"/> <see cref="object.ToString()"/> (in the invariant culture)
+ /// is in the <see cref="Keys"/>; otherwise <c>false</c>
/// </summary>
- public virtual bool ContainsKey(object o)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ public virtual bool ContainsKey<T>(T text)
{
- if (o is null)
- {
- throw new ArgumentNullException(nameof(o), "o can't be null"); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
- }
-
- var c = o as char[];
- if (c != null)
- {
- var text = c;
- return ContainsKey(text, 0, text.Length);
- }
- return ContainsKey(o.ToString());
+ if (text is null)
+ throw new ArgumentNullException(nameof(text)); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
+
+ if (text is string str)
+ return ContainsKey(str);
+ if (text is char[] charArray)
+ return ContainsKey(charArray, 0, charArray.Length);
+ if (text is ICharSequence cs)
+ return ContainsKey(cs);
+
+ var returnType = CharArrayDictionary.ConvertObjectToChars(text, out char[] chars, out string s);
+ if (returnType == CharArrayDictionary.CharReturnType.String)
+ return ContainsKey(s);
+ else
+ return ContainsKey(chars);
}
+ #region Get
+
/// <summary>
- /// returns the value of the mapping of <paramref name="length"/> chars of <paramref name="text"/>
- /// starting at <paramref name="offset"/>
+ /// Returns the value of the mapping of <paramref name="length"/> chars of <paramref name="text"/>
+ /// starting at <paramref name="startIndex"/>.
/// </summary>
- public virtual TValue Get(char[] text, int offset, int length)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref name="length"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="startIndex"/> and <paramref name="length"/> refer to a position outside of <paramref name="text"/>.</exception>
+ /// <exception cref="KeyNotFoundException">The effective text is not found in the dictionary.</exception>
+ internal virtual TValue Get(char[] text, int startIndex, int length, bool throwIfNotFound = true)
{
- var value = values[GetSlot(text, offset, length)];
- return (value != null) ? value.Value : default;
+ MapValue? value = values[GetSlot(text, startIndex, length)];
+ if (value is not null)
+ {
+ return value.Value;
+ }
+ if (throwIfNotFound)
+ throw new KeyNotFoundException(string.Format(SR.Arg_KeyNotFoundWithKey, new string(text, startIndex, length)));
+ return default!;
}
/// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
+ /// Returns the value of the mapping of the chars inside this <paramref name="text"/>.
/// </summary>
- public virtual TValue Get(char[] text)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="KeyNotFoundException"><paramref name="text"/> is not found in the dictionary.</exception>
+ internal virtual TValue Get(char[] text, bool throwIfNotFound = true)
{
- var value = values[GetSlot(text, 0, text.Length)];
- return (value != null) ? value.Value : default;
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ MapValue? value = values[GetSlot(text, 0, text.Length)];
+ if (value is not null)
+ {
+ return value.Value;
+ }
+ if (throwIfNotFound)
+ throw new KeyNotFoundException(string.Format(SR.Arg_KeyNotFoundWithKey, new string(text)));
+ return default!;
}
/// <summary>
- /// returns the value of the mapping of the chars inside this <see cref="ICharSequence"/>
+ /// Returns the value of the mapping of the chars inside this <see cref="ICharSequence"/>.
/// </summary>
- public virtual TValue Get(ICharSequence text)
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="text"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <paramref name="text"/>'s <see cref="ICharSequence.HasValue"/> property returns <c>false</c>.
+ /// </exception>
+ /// <exception cref="KeyNotFoundException"><paramref name="text"/> is not found in the dictionary.</exception>
+ internal virtual TValue Get(ICharSequence text, bool throwIfNotFound = true)
{
+ if (text is null || !text.HasValue)
+ throw new ArgumentNullException(nameof(text));
+
+ if (text is StringCharSequence strCs)
+ return Get(strCs.Value!, throwIfNotFound);
+ if (text is CharArrayCharSequence charArrayCs)
+ return Get(charArrayCs.Value!, throwIfNotFound);
+ if (text is StringBuilderCharSequence stringBuilderCs)
+ return Get(stringBuilderCs.Value!.ToString(), throwIfNotFound); // LUCENENET: Indexing into a StringBuilder is slow, so materialize
+
var value = values[GetSlot(text)];
- return (value != null) ? value.Value : default;
+ if (value is not null)
+ {
+ return value.Value;
+ }
+ if (throwIfNotFound)
+ throw new KeyNotFoundException(string.Format(SR.Arg_KeyNotFoundWithKey, text));
+ return default!;
}
/// <summary>
- /// returns the value of the mapping of the chars inside this <see cref="string"/>
+ /// Returns the value of the mapping of the chars inside this <see cref="string"/>.
/// </summary>
- public virtual TValue Get(string text)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="KeyNotFoundException"><paramref name="text"/> is not found in the dictionary.</exception>
+ internal virtual TValue Get(string text, bool throwIfNotFound = true)
{
var value = values[GetSlot(text)];
- return (value != null) ? value.Value : default;
+ if (value is not null)
+ {
+ return value.Value;
+ }
+ if (throwIfNotFound)
+ throw new KeyNotFoundException(string.Format(SR.Arg_KeyNotFoundWithKey, text));
+ return default!;
}
/// <summary>
- /// returns the value of the mapping of the chars inside this <see cref="object.ToString()"/>
+ /// Returns the value of the mapping of the chars inside this <see cref="object.ToString()"/>.
/// </summary>
- public virtual TValue Get(object o)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="KeyNotFoundException"><paramref name="text"/> is not found in the dictionary.</exception>
+ internal virtual TValue Get<T>(T text, bool throwIfNotFound = true)
{
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
// LUCENENET NOTE: Testing for *is* is at least 10x faster
// than casting using *as* and then checking for null.
// http://stackoverflow.com/q/1583050/181087
- if (o is char[])
- {
- var text = o as char[];
- return Get(text, 0, text.Length);
- }
- return Get(o.ToString());
+ if (text is string str)
+ return Get(str, throwIfNotFound);
+ if (text is char[] charArray)
+ return Get(charArray, 0, charArray.Length, throwIfNotFound);
+ if (text is ICharSequence cs)
+ return Get(cs, throwIfNotFound);
+
+ var returnType = CharArrayDictionary.ConvertObjectToChars(text, out char[] chars, out string s);
+ if (returnType == CharArrayDictionary.CharReturnType.String)
+ return Get(s, throwIfNotFound);
+ else
+ return Get(chars, throwIfNotFound);
}
- private int GetSlot(char[] text, int offset, int length)
+ #endregion Get
+
+ #region GetSlot
+
+ private int GetSlot(char[] text, int startIndex, int length)
{
- int code = GetHashCode(text, offset, length);
+ int code = GetHashCode(text, startIndex, length);
int pos = code & (keys.Length - 1);
char[] text2 = keys[pos];
- if (text2 != null && !Equals(text, offset, length, text2))
+ if (text2 != null && !Equals(text, startIndex, length, text2))
{
int inc = ((code >> 8) + code) | 1;
do
@@ -374,14 +664,21 @@ namespace Lucene.Net.Analysis.Util
code += inc;
pos = code & (keys.Length - 1);
text2 = keys[pos];
- } while (text2 != null && !Equals(text, offset, length, text2));
+ } while (text2 != null && !Equals(text, startIndex, length, text2));
}
return pos;
}
/// <summary>
- /// Returns true if the <see cref="ICharSequence"/> is in the set
+ /// Returns <c>true</c> if the <see cref="ICharSequence"/> is in the set.
/// </summary>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="text"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <paramref name="text"/>'s <see cref="ICharSequence.HasValue"/> property returns <c>false</c>.
+ /// </exception>
private int GetSlot(ICharSequence text)
{
int code = GetHashCode(text);
@@ -401,8 +698,9 @@ namespace Lucene.Net.Analysis.Util
}
/// <summary>
- /// Returns true if the <see cref="string"/> is in the set
+ /// Returns <c>true</c> if the <see cref="string"/> is in the set.
/// </summary>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
private int GetSlot(string text)
{
int code = GetHashCode(text);
@@ -421,84 +719,289 @@ namespace Lucene.Net.Analysis.Util
return pos;
}
+ #endregion GetSlot
+
+ #region Put (value)
+
/// <summary>
/// Add the given mapping.
- /// </summary>
- public virtual TValue Put(ICharSequence text, TValue value)
- {
- MapValue oldValue = PutImpl(text, new MapValue(value)); // could be more efficient
- return (oldValue != null) ? oldValue.Value : default;
+ /// If ignoreCase is <c>true</c> for this dictionary, the text array will be directly modified.
+ /// <para/>
+ /// <b>Note:</b> The <see cref="this[char[]]"/> setter is more efficient than this method if
+ /// the <paramref name="previousValue"/> is not required.
+ /// </summary>
+ /// <param name="text">A text with which the specified <paramref name="value"/> is associated.</param>
+ /// <param name="startIndex">The position of the <paramref name="text"/> where the target text begins.</param>
+ /// <param name="length">The total length of the <paramref name="text"/>.</param>
+ /// <param name="value">The value to be associated with the specified <paramref name="text"/>.</param>
+ /// <param name="previousValue">The previous value associated with the text, or the default for the type of <paramref name="value"/>
+ /// parameter if there was no mapping for <paramref name="text"/>.</param>
+ /// <returns><c>true</c> if the mapping was added, <c>false</c> if the text already existed. The <paramref name="previousValue"/>
+ /// will be populated if the result is <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref name="length"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="startIndex"/> and <paramref name="length"/> refer to a position outside of <paramref name="text"/>.</exception>
+ public virtual bool Put(char[] text, int startIndex, int length, TValue value, [MaybeNullWhen(returnValue: true)] out TValue previousValue) // LUCENENET: Refactored to use out value to support value types
+ {
+ MapValue? oldValue = PutImpl(text, startIndex, length, new MapValue(value));
+ if (oldValue is not null)
+ {
+ previousValue = oldValue.Value;
+ return false;
+ }
+ previousValue = default;
+ return true;
}
/// <summary>
- /// Add the given mapping using the <see cref="object.ToString()"/> representation
- /// of <paramref name="o"/> in the <see cref="CultureInfo.InvariantCulture"/>.
- /// </summary>
- public virtual TValue Put(object o, TValue value)
- {
- MapValue oldValue = PutImpl(o, new MapValue(value));
- return (oldValue != null) ? oldValue.Value : default;
+ /// Add the given mapping.
+ /// If ignoreCase is <c>true</c> for this dictionary, the text array will be directly modified.
+ /// The user should never modify this text array after calling this method.
+ /// <para/>
+ /// <b>Note:</b> The <see cref="this[char[]]"/> setter is more efficient than this method if
+ /// the <paramref name="previousValue"/> is not required.
+ /// </summary>
+ /// <param name="text">A text with which the specified <paramref name="value"/> is associated.</param>
+ /// <param name="value">The value to be associated with the specified <paramref name="text"/>.</param>
+ /// <param name="previousValue">The previous value associated with the text, or the default for the type of <paramref name="value"/>
+ /// parameter if there was no mapping for <paramref name="text"/>.</param>
+ /// <returns><c>true</c> if the mapping was added, <c>false</c> if the text already existed. The <paramref name="previousValue"/>
+ /// will be populated if the result is <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ public virtual bool Put(char[] text, TValue value, [MaybeNullWhen(returnValue: true)] out TValue previousValue) // LUCENENET: Refactored to use out value to support value types
+ {
+ MapValue? oldValue = PutImpl(text, new MapValue(value));
+ if (oldValue is not null)
+ {
+ previousValue = oldValue.Value;
+ return false;
+ }
+ previousValue = default;
+ return true;
}
/// <summary>
/// Add the given mapping.
- /// </summary>
- public virtual TValue Put(string text, TValue value)
- {
- MapValue oldValue = PutImpl(text, new MapValue(value));
- return (oldValue != null) ? oldValue.Value : default;
+ /// <para/>
+ /// <b>Note:</b> The <see cref="this[string]"/> setter is more efficient than this method if
+ /// the <paramref name="previousValue"/> is not required.
+ /// </summary>
+ /// <param name="text">A text with which the specified <paramref name="value"/> is associated.</param>
+ /// <param name="value">The value to be associated with the specified <paramref name="text"/>.</param>
+ /// <param name="previousValue">The previous value associated with the text, or the default for the type of <paramref name="value"/>
+ /// parameter if there was no mapping for <paramref name="text"/>.</param>
+ /// <returns><c>true</c> if the mapping was added, <c>false</c> if the text already existed. The <paramref name="previousValue"/>
+ /// will be populated if the result is <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ public virtual bool Put(string text, TValue value, [MaybeNullWhen(returnValue: true)] out TValue previousValue) // LUCENENET: Refactored to use out value to support value types
+ {
+ MapValue? oldValue = PutImpl(text, new MapValue(value));
+ if (oldValue is not null)
+ {
+ previousValue = oldValue.Value;
+ return false;
+ }
+ previousValue = default;
+ return true;
}
/// <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 TValue Put(char[] text, TValue value)
- {
- MapValue oldValue = PutImpl(text, new MapValue(value));
- return (oldValue != null) ? oldValue.Value : default;
+ /// <para/>
+ /// <b>Note:</b> The <see cref="this[ICharSequence]"/> setter is more efficient than this method if
+ /// the <paramref name="previousValue"/> is not required.
+ /// </summary>
+ /// <param name="text">A text with which the specified <paramref name="value"/> is associated.</param>
+ /// <param name="value">The value to be associated with the specified <paramref name="text"/>.</param>
+ /// <param name="previousValue">The previous value associated with the text, or the default for the type of <paramref name="value"/>
+ /// parameter if there was no mapping for <paramref name="text"/>.</param>
+ /// <returns><c>true</c> if the mapping was added, <c>false</c> if the text already existed. The <paramref name="previousValue"/>
+ /// will be populated if the result is <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="text"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <paramref name="text"/>'s <see cref="ICharSequence.HasValue"/> property returns <c>false</c>.
+ /// </exception>
+ public virtual bool Put(ICharSequence text, TValue value, [MaybeNullWhen(returnValue: true)] out TValue previousValue) // LUCENENET: Refactored to use out value to support value types
+ {
+ MapValue? oldValue = PutImpl(text, new MapValue(value));
+ if (oldValue is not null)
+ {
+ previousValue = oldValue.Value;
+ return false;
+ }
+ previousValue = default;
+ return true;
+ }
+
+ /// <summary>
+ /// Add the given mapping using the <see cref="object.ToString()"/> representation
+ /// of <paramref name="text"/> in the <see cref="CultureInfo.InvariantCulture"/>.
+ /// <para/>
+ /// <b>Note:</b> The <see cref="this[object]"/> setter is more efficient than this method if
+ /// the <paramref name="previousValue"/> is not required.
+ /// </summary>
+ /// <param name="text">A text with which the specified <paramref name="value"/> is associated.</param>
+ /// <param name="value">The value to be associated with the specified <paramref name="text"/>.</param>
+ /// <param name="previousValue">The previous value associated with the text, or the default for the type of <paramref name="value"/>
+ /// parameter if there was no mapping for <paramref name="text"/>.</param>
+ /// <returns><c>true</c> if the mapping was added, <c>false</c> if the text already existed. The <paramref name="previousValue"/>
+ /// will be populated if the result is <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ public virtual bool Put<T>(T text, TValue value, [MaybeNullWhen(returnValue: true)] out TValue previousValue) // LUCENENET: Refactored to use out value to support value types
+ {
+ MapValue? oldValue = PutImpl(text, new MapValue(value));
+ if (oldValue is not null)
+ {
+ previousValue = oldValue.Value;
+ return false;
+ }
+ previousValue = default;
+ return true;
}
+ #endregion Put (value)
+
+ #region PutImpl
+
/// <summary>
/// Add the given mapping.
/// </summary>
- private MapValue PutImpl(ICharSequence text, MapValue value)
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="text"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <paramref name="text"/>'s <see cref="ICharSequence.HasValue"/> property returns <c>false</c>.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private MapValue? PutImpl(ICharSequence text, MapValue value)
{
- return PutImpl(text.ToString(), value); // could be more efficient
+ // LUCENENET: Added guard clause
+ if (text is null || !text.HasValue)
+ throw new ArgumentNullException(nameof(text));
+
+ if (text is CharArrayCharSequence charArrayCs)
+ return PutImpl(charArrayCs.Value ?? Arrays.Empty<char>(), value);
+ if (text is StringBuilderCharSequence stringBuilderCs) // LUCENENET: Indexing into a StringBuilder is slow, so materialize
+ {
+ var sb = stringBuilderCs.Value!;
+ char[] result = new char[sb.Length];
+ sb.CopyTo(sourceIndex: 0, result, destinationIndex: 0, sb.Length);
+ return PutImpl(result, value);
+ }
+
+ int length = text.Length;
+ char[] buffer = new char[length];
+ for (int i = 0; i < length; i++)
+ {
+ buffer[i] = text[i];
+ }
+ return PutImpl(buffer, value);
}
- private MapValue PutImpl(object o, MapValue value)
+ /// <summary>
+ /// Add the given mapping.
+ /// </summary>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private MapValue? PutImpl<T>(T text, MapValue value)
{
+ // LUCENENET: Added guard clause
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
// LUCENENET NOTE: Testing for *is* is at least 10x faster
// than casting using *as* and then checking for null.
// http://stackoverflow.com/q/1583050/181087
- if (o is char[])
+ if (text is string str)
+ return PutImpl(str, value);
+ if (text is char[] charArray)
+ return PutImpl(charArray, value);
+ if (text is ICharSequence cs)
+ return PutImpl(cs, value);
+
+ var returnType = CharArrayDictionary.ConvertObjectToChars(text, out char[] chars, out string s);
+ if (returnType == CharArrayDictionary.CharReturnType.String)
+ return PutImpl(s, value);
+ else
+ return PutImpl(chars, value);
+ }
+
+ /// <summary>
+ /// Add the given mapping.
+ /// </summary>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private MapValue? PutImpl(string text, MapValue value)
+ {
+ // LUCENENET: Added guard clause
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ // LUCENENET specific - only allocate char array if it is required.
+ if (ignoreCase)
+ {
+ return PutImpl(text.ToCharArray(), value);
+ }
+ version++;
+ int slot = GetSlot(text);
+ if (keys[slot] != null)
{
- var c = o as char[];
- return PutImpl(c, value);
+ MapValue oldValue = values[slot];
+ values[slot] = value;
+ return oldValue;
}
- // LUCENENET: We need value types to be represented using the invariant
- // culture, so it is consistent regardless of the current culture.
- // It's easy to work out if this is a value type, but difficult
- // to get to the ToString(IFormatProvider) overload of the type without
- // a lot of special cases. It's easier just to change the culture of the
- // thread before calling ToString(), but we don't want that behavior to
- // bleed into PutImpl.
- string s;
- using (var context = new CultureContext(CultureInfo.InvariantCulture))
+ keys[slot] = text.ToCharArray();
+ values[slot] = value;
+ count++;
+
+ if (count + (count >> 2) > keys.Length)
{
- s = o.ToString();
+ Rehash();
}
- return PutImpl(s, value);
+
+ return null;
}
- /// <summary>
- /// Add the given mapping.
- /// </summary>
- private MapValue PutImpl(string text, MapValue value)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private MapValue? PutImpl(char[] text, int startIndex, int length, MapValue value)
{
- return PutImpl(text.ToCharArray(), value);
+ // LUCENENET: Added guard clause
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (length < 0)
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (startIndex > text.Length - length) // Checks for int overflow
+ throw new ArgumentException(SR.ArgumentOutOfRange_IndexLength);
+
+ version++;
+
+ if (ignoreCase)
+ {
+ charUtils.ToLower(text, startIndex, length);
+ }
+ int slot = GetSlot(text, startIndex, length);
+ if (keys[slot] != null)
+ {
+ MapValue oldValue = values[slot];
+ values[slot] = value;
+ return oldValue;
+ }
+ keys[slot] = text.AsSpan(startIndex, length).ToArray();
+ values[slot] = value;
+ count++;
+
+ if (count + (count >> 2) > keys.Length)
+ {
+ Rehash();
+ }
+
+ return null;
}
/// <summary>
@@ -507,8 +1010,16 @@ namespace Lucene.Net.Analysis.Util
/// so we know whether or not the value was set, since we can't reliably do
/// a check for <c>null</c> on the <typeparamref name="TValue"/> type.
/// </summary>
- private MapValue PutImpl(char[] text, MapValue value)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private MapValue? PutImpl(char[] text, MapValue value)
{
+ // LUCENENET: Added guard clause
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ version++;
+
if (ignoreCase)
{
charUtils.ToLower(text, 0, text.Length);
@@ -532,114 +1043,579 @@ namespace Lucene.Net.Analysis.Util
return null;
}
- #region PutAll
+ #endregion PutImpl
+
+ #region Set
/// <summary>
- /// This implementation enumerates over the specified <see cref="T:IDictionary{char[],TValue}"/>'s
- /// entries, and calls this map's <see cref="Put(char[], TValue)"/> operation once for each entry.
+ /// Sets the value of the mapping of the chars inside this <paramref name="text"/>.
/// </summary>
- /// <param name="collection">A dictionary of values to add/update in the current map.</param>
- public virtual void PutAll(IDictionary<char[], TValue> collection)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal virtual void Set(char[] text, int startIndex, int length)
{
- foreach (var kvp in collection)
- {
- Put(kvp.Key, kvp.Value);
- }
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ SetImpl(text, startIndex, length, PLACEHOLDER);
}
/// <summary>
- /// This implementation enumerates over the specified <see cref="T:IDictionary{string,TValue}"/>'s
- /// entries, and calls this map's <see cref="Put(string, TValue)"/> operation once for each entry.
+ /// Sets the value of the mapping of the chars inside this <paramref name="text"/>.
/// </summary>
- /// <param name="collection">A dictionary of values to add/update in the current map.</param>
- public virtual void PutAll(IDictionary<string, TValue> collection)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal virtual void Set(char[] text)
{
- foreach (var kvp in collection)
- {
- Put(kvp.Key, kvp.Value);
- }
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ SetImpl(text, PLACEHOLDER);
}
/// <summary>
- /// This implementation enumerates over the specified <see cref="T:IDictionary{ICharSequence,TValue}"/>'s
- /// entries, and calls this map's <see cref="Put(ICharSequence, TValue)"/> operation once for each entry.
+ /// Sets the value of the mapping of the chars inside this <see cref="ICharSequence"/>.
/// </summary>
- /// <param name="collection">A dictionary of values to add/update in the current map.</param>
- public virtual void PutAll(IDictionary<ICharSequence, TValue> collection)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal virtual void Set(ICharSequence text)
{
- foreach (var kvp in collection)
- {
- Put(kvp.Key, kvp.Value);
- }
+ if (text is null || !text.HasValue)
+ throw new ArgumentNullException(nameof(text));
+
+ SetImpl(text, PLACEHOLDER);
}
/// <summary>
- /// This implementation enumerates over the specified <see cref="T:IDictionary{object,TValue}"/>'s
- /// entries, and calls this map's <see cref="Put(object, TValue)"/> operation once for each entry.
+ /// Sets the value of the mapping of the chars inside this <see cref="string"/>.
/// </summary>
- /// <param name="collection">A dictionary of values to add/update in the current map.</param>
- public virtual void PutAll(IDictionary<object, TValue> collection)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal virtual void Set(string text)
{
- foreach (var kvp in collection)
- {
- Put(kvp.Key, kvp.Value);
- }
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ SetImpl(text, PLACEHOLDER);
}
/// <summary>
- /// This implementation enumerates over the specified <see cref="T:IEnumerable{KeyValuePair{char[],TValue}}"/>'s
- /// entries, and calls this map's <see cref="Put(char[], TValue)"/> operation once for each entry.
+ /// Sets the value of the mapping of the chars inside this <see cref="object.ToString()"/>.
/// </summary>
- /// <param name="collection">The values to add/update in the current map.</param>
- public virtual void PutAll(IEnumerable<KeyValuePair<char[], TValue>> collection)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ internal virtual void Set<T>(T text)
{
- foreach (var kvp in collection)
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ // LUCENENET NOTE: Testing for *is* is at least 10x faster
+ // than casting using *as* and then checking for null.
+ // http://stackoverflow.com/q/1583050/181087
+ if (text is string str)
{
- Put(kvp.Key, kvp.Value);
+ Set(str);
+ return;
+ }
+ if (text is char[] charArray)
+ {
+ Set(charArray);
+ return;
+ }
+ if (text is ICharSequence cs)
+ {
+ Set(cs);
+ return;
}
- }
- /// <summary>
- /// This implementation enumerates over the specified <see cref="T:IEnumerable{KeyValuePair{string,TValue}}"/>'s
- /// entries, and calls this map's <see cref="Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="collection">The values to add/update in the current map.</param>
- public virtual void PutAll(IEnumerable<KeyValuePair<string, TValue>> collection)
- {
- foreach (var kvp in collection)
+ var returnType = CharArrayDictionary.ConvertObjectToChars(text, out char[] chars, out string s);
+ if (returnType == CharArrayDictionary.CharReturnType.String)
{
- Put(kvp.Key, kvp.Value);
+ Set(s);
+ return;
}
+
+ Set(chars);
}
+ void ICharArrayDictionary.Set(char[] text, int startIndex, int length) => Set(text, startIndex, length);
+ void ICharArrayDictionary.Set(char[] text) => Set(text);
+ void ICharArrayDictionary.Set(ICharSequence text) => Set(text);
+ void ICharArrayDictionary.Set<T>(T text) => Set(text);
+ void ICharArrayDictionary.Set(string text) => Set(text);
+
+ #endregion Set
+
+ #region Set (value)
+
/// <summary>
- /// This implementation enumerates over the specified <see cref="T:IEnumerable{KeyValuePair{ICharSequence,TValue}}"/>'s
- /// entries, and calls this map's <see cref="Put(ICharSequence, TValue)"/> operation once for each entry.
+ /// Sets the value of the mapping of <paramref name="length"/> chars of <paramref name="text"/>
+ /// starting at <paramref name="startIndex"/>.
+ /// <para/>
+ /// If ignoreCase is <c>true</c> for this dictionary, the text array will be directly modified.
/// </summary>
- /// <param name="collection">The values to add/update in the current map.</param>
+ /// <param name="text">A text with which the specified <paramref name="value"/> is associated.</param>
+ /// <param name="startIndex">The position of the <paramref name="text"/> where the target text begins.</param>
+ /// <param name="length">The total length of the <paramref name="text"/>.</param>
+ /// <param name="value">The value to be associated with the specified <paramref name="text"/>.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref name="length"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="startIndex"/> and <paramref name="length"/> refer to a position outside of <paramref name="text"/>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal virtual void Set(char[] text, int startIndex, int length, TValue? value)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ SetImpl(text, startIndex, length, new MapValue(value));
+ }
+
+ /// <summary>
+ /// Sets the value of the mapping of the chars inside this <paramref name="text"/>.
+ /// <para/>
+ /// If ignoreCase is <c>true</c> for this dictionary, the text array will be directly modified.
+ /// The user should never modify this text array after calling this method.
+ /// </summary>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal virtual void Set(char[] text, TValue? value)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ SetImpl(text, new MapValue(value));
+ }
+
+ /// <summary>
+ /// Sets the value of the mapping of the chars inside this <see cref="ICharSequence"/>.
+ /// </summary>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="text"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <paramref name="text"/>'s <see cref="ICharSequence.HasValue"/> property returns <c>false</c>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal virtual void Set(ICharSequence text, TValue? value)
+ {
+ if (text is null || !text.HasValue)
+ throw new ArgumentNullException(nameof(text));
+
+ SetImpl(text, new MapValue(value));
+ }
+
+ /// <summary>
+ /// Sets the value of the mapping of the chars inside this <see cref="string"/>.
+ /// </summary>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal virtual void Set(string text, TValue? value)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ SetImpl(text, new MapValue(value));
+ }
+
+ /// <summary>
+ /// Sets the value of the mapping of the chars inside this <see cref="object.ToString()"/>.
+ /// </summary>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal virtual void Set<T>(T text, TValue? value)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ // LUCENENET NOTE: Testing for *is* is at least 10x faster
+ // than casting using *as* and then checking for null.
+ // http://stackoverflow.com/q/1583050/181087
+ if (text is string str)
+ {
+ Set(str, value);
+ return;
+ }
+ if (text is char[] charArray)
+ {
+ Set(charArray, 0, charArray.Length, value);
+ return;
+ }
+ if (text is ICharSequence cs)
+ {
+ Set(cs, value);
+ return;
+ }
+
+ var returnType = CharArrayDictionary.ConvertObjectToChars(text, out char[] chars, out string s);
+ if (returnType == CharArrayDictionary.CharReturnType.String)
+ {
+ Set(s, value);
+ return;
+ }
+
+ Set(chars, value);
+ }
+
+ #endregion Set (value)
+
+ #region SetImpl
+
+ /// <summary>
+ /// LUCENENET specific. Like PutImpl, but doesn't have a return value or lookup to get the old value.
+ /// </summary>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="text"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <paramref name="text"/>'s <see cref="ICharSequence.HasValue"/> property returns <c>false</c>.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void SetImpl(ICharSequence text, MapValue value)
+ {
+ // LUCENENET: Added guard clause
+ if (text is null || !text.HasValue)
+ throw new ArgumentNullException(nameof(text));
+
+ if (text is CharArrayCharSequence charArrayCs)
+ {
+ SetImpl(charArrayCs.Value ?? Arrays.Empty<char>(), value);
+ return;
+ }
+ if (text is StringBuilderCharSequence stringBuilderCs) // LUCENENET: Indexing into a StringBuilder is slow, so materialize
+ {
+ var sb = stringBuilderCs.Value!;
+ char[] result = new char[sb.Length];
+ sb.CopyTo(sourceIndex: 0, result, destinationIndex: 0, sb.Length);
+ SetImpl(result, value);
+ return;
+ }
+
+ int length = text.Length;
+ char[] buffer = new char[length];
+ for (int i = 0; i < length; i++)
+ {
+ buffer[i] = text[i];
+ }
+
+ SetImpl(buffer, value);
+ }
+
+ /// <summary>
+ /// LUCENENET specific. Like PutImpl, but doesn't have a return value or lookup to get the old value.
+ /// </summary>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void SetImpl(string text, MapValue value)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ // LUCENENET specific - only allocate char array if it is required.
+ if (ignoreCase)
+ {
+ SetImpl(text.ToCharArray(), value);
+ return;
+ }
+ version++;
+ int slot = GetSlot(text);
+ if (keys[slot] != null)
+ {
+ values[slot] = value;
+ return;
+ }
+ keys[slot] = text.ToCharArray();
+ values[slot] = value;
+ count++;
+
+ if (count + (count >> 2) > keys.Length)
+ {
+ Rehash();
+ }
+ }
+
+ /// <summary>
+ /// LUCENENET specific. Like PutImpl, but doesn't have a return value or lookup to get the old value.
+ /// </summary>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void SetImpl(char[] text, MapValue value)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ version++;
+ if (ignoreCase)
+ {
+ charUtils.ToLower(text, 0, text.Length);
+ }
+ int slot = GetSlot(text, 0, text.Length);
+ if (keys[slot] != null)
+ {
+ values[slot] = value;
+ return;
+ }
+ keys[slot] = text;
+ values[slot] = value;
+ count++;
+
+ if (count + (count >> 2) > keys.Length)
+ {
+ Rehash();
+ }
+ }
+
+ /// <summary>
+ /// LUCENENET specific. Like PutImpl, but doesn't have a return value or lookup to get the old value.
+ /// </summary>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref name="length"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="startIndex"/> and <paramref name="length"/> refer to a position outside of <paramref name="text"/>.</exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private void SetImpl(char[] text, int startIndex, int length, MapValue value)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (length < 0)
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (startIndex > text.Length - length) // Checks for int overflow
+ throw new ArgumentException(SR.ArgumentOutOfRange_IndexLength);
+
+ version++;
+ if (ignoreCase)
+ {
+ charUtils.ToLower(text, startIndex, length);
+ }
+ int slot = GetSlot(text, startIndex, length);
+ if (keys[slot] != null)
+ {
+ values[slot] = value;
+ return;
+ }
+ keys[slot] = text.AsSpan(startIndex, length).ToArray();
+ values[slot] = value;
+ count++;
+
+ if (count + (count >> 2) > keys.Length)
+ {
+ Rehash();
+ }
+ }
+
+ #endregion SetImpl
+
+ #region PutAll
+
+ /// <summary>
+ /// This implementation enumerates over the specified <see cref="T:IDictionary{char[],TValue}"/>'s
+ /// entries, and calls this dictionary's <see cref="Set(char[], TValue?)"/> operation once for each entry.
+ /// <para/>
+ /// If ignoreCase is <c>true</c> for this dictionary, the text arrays will be directly modified.
+ /// The user should never modify the text arrays after calling this method.
+ /// </summary>
+ /// <param name="collection">A dictionary of values to add/update in the current dictionary.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// An element in the collection is <c>null</c>.
+ /// </exception>
+ public virtual void PutAll(IDictionary<char[], TValue> collection)
+ {
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ foreach (var kvp in collection)
+ {
+ Set(kvp.Key, kvp.Value);
+ }
+ }
+
+ /// <summary>
+ /// This implementation enumerates over the specified <see cref="T:IDictionary{string,TValue}"/>'s
+ /// entries, and calls this dictionary's <see cref="Set(string, TValue?)"/> operation once for each entry.
+ /// </summary>
+ /// <param name="collection">A dictionary of values to add/update in the current dictionary.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// An element in the collection is <c>null</c>.
+ /// </exception>
+ public virtual void PutAll(IDictionary<string, TValue> collection)
+ {
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ foreach (var kvp in collection)
+ {
+ Set(kvp.Key, kvp.Value);
+ }
+ }
+
+ /// <summary>
+ /// This implementation enumerates over the specified <see cref="T:IDictionary{ICharSequence,TValue}"/>'s
+ /// entries, and calls this dictionary's <see cref="Set(ICharSequence, TValue?)"/> operation once for each entry.
+ /// </summary>
+ /// <param name="collection">A dictionary of values to add/update in the current dictionary.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// An element in the collection has a <c>null</c> text.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The text's <see cref="ICharSequence.HasValue"/> property for a given element in the collection returns <c>false</c>.
+ /// </exception>
+ public virtual void PutAll(IDictionary<ICharSequence, TValue> collection)
+ {
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ foreach (var kvp in collection)
+ {
+ Set(kvp.Key, kvp.Value);
+ }
+ }
+
+ /// <summary>
+ /// This implementation enumerates over the specified <see cref="T:IDictionary{T,TValue}"/>'s
+ /// entries, and calls this dictionary's <see cref="Set{T}(T, TValue?)"/> operation once for each entry.
+ /// </summary>
+ /// <param name="collection">A dictionary of values to add/update in the current dictionary.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// An element in the collection is <c>null</c>.
+ /// </exception>
+ public virtual void PutAll<T>(IDictionary<T, TValue> collection)
+ {
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ foreach (var kvp in collection)
+ {
+ Set(kvp.Key, kvp.Value);
+ }
+ }
+
+ /// <summary>
+ /// This implementation enumerates over the specified <see cref="T:IEnumerable{KeyValuePair{char[],TValue}}"/>'s
+ /// entries, and calls this dictionary's <see cref="Set(char[], TValue?)"/> operation once for each entry.
+ /// </summary>
+ /// <param name="collection">The values to add/update in the current dictionary.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// An element in the collection is <c>null</c>.
+ /// </exception>
+ public virtual void PutAll(IEnumerable<KeyValuePair<char[], TValue>> collection)
+ {
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ foreach (var kvp in collection)
+ {
+ Set(kvp.Key, kvp.Value);
+ }
+ }
+
+ /// <summary>
+ /// This implementation enumerates over the specified <see cref="T:IEnumerable{KeyValuePair{string,TValue}}"/>'s
+ /// entries, and calls this dictionary's <see cref="Set(string, TValue)"/> operation once for each entry.
+ /// </summary>
+ /// <param name="collection">The values to add/update in the current dictionary.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// An element in the collection is <c>null</c>.
+ /// </exception>
+ public virtual void PutAll(IEnumerable<KeyValuePair<string, TValue>> collection)
+ {
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ foreach (var kvp in collection)
+ {
+ Set(kvp.Key, kvp.Value);
+ }
+ }
+
+ /// <summary>
+ /// This implementation enumerates over the specified <see cref="T:IEnumerable{KeyValuePair{ICharSequence,TValue}}"/>'s
+ /// entries, and calls this dictionary's <see cref="Set(ICharSequence, TValue)"/> operation once for each entry.
+ /// </summary>
+ /// <param name="collection">The values to add/update in the current dictionary.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// An element in the collection has a <c>null</c> text.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The text's <see cref="ICharSequence.HasValue"/> property for a given element in the collection returns <c>false</c>.
+ /// </exception>
public virtual void PutAll(IEnumerable<KeyValuePair<ICharSequence, TValue>> collection)
{
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
foreach (var kvp in collection)
{
- Put(kvp.Key, kvp.Value);
+ Set(kvp.Key, kvp.Value);
}
}
/// <summary>
- /// This implementation enumerates over the specified <see cref="T:IEnumerable{KeyValuePair{object,TValue}}"/>'s
- /// entries, and calls this map's <see cref="Put(object, TValue)"/> operation once for each entry.
+ /// This implementation enumerates over the specified <see cref="T:IEnumerable{KeyValuePair{TKey,TValue}}"/>'s
+ /// entries, and calls this dictionary's <see cref="Set{T}(T, TValue?)"/> operation once for each entry.
/// </summary>
- /// <param name="collection">The values to add/update in the current map.</param>
- public virtual void PutAll(IEnumerable<KeyValuePair<object, TValue>> collection)
+ /// <param name="collection">The values to add/update in the current dictionary.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// An element in the collection is <c>null</c>.
+ /// </exception>
+ public virtual void PutAll<T>(IEnumerable<KeyValuePair<T, TValue>> collection)
{
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+#if FEATURE_SPANFORMATTABLE
+ Span<char> buffer = stackalloc char[256];
+#else
+ Span<char> buffer = stackalloc char[1];
+#endif
+
foreach (var kvp in collection)
{
- Put(kvp.Key, kvp.Value);
+ // Convert the item to chars in the invariant culture
+ var returnType = CharArrayDictionary.ConvertObjectToChars(kvp.Key, out char[] chars, out string s, buffer);
+ if (returnType == CharArrayDictionary.CharReturnType.String)
+ Set(s, kvp.Value);
+ else
+ Set(chars, kvp.Value);
}
}
#endregion
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Rehash()
{
if (Debugging.AssertsEnabled) Debugging.Assert(keys.Length == values.Length);
@@ -662,18 +1638,19 @@ namespace Lucene.Net.Analysis.Util
}
}
- private bool Equals(char[] text1, int offset, int length, char[] text2)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private bool Equals(char[] text1, int startIndex, int length, char[] text2)
{
if (length != text2.Length)
{
return false;
}
- int limit = offset + length;
+ int limit = startIndex + length;
if (ignoreCase)
{
for (int i = 0; i < length;)
{
- var codePointAt = charUtils.CodePointAt(text1, offset + i, limit);
+ var codePointAt = charUtils.CodePointAt(text1, startIndex + i, limit);
if (Character.ToLower(codePointAt, CultureInfo.InvariantCulture) != charUtils.CodePointAt(text2, i, text2.Length)) // LUCENENET specific - need to use invariant culture to match Java
{
return false;
@@ -685,7 +1662,7 @@ namespace Lucene.Net.Analysis.Util
{
for (int i = 0; i < length; i++)
{
- if (text1[offset + i] != text2[i])
+ if (text1[startIndex + i] != text2[i])
{
return false;
}
@@ -694,6 +1671,7 @@ namespace Lucene.Net.Analysis.Util
return true;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool Equals(ICharSequence text1, char[] text2)
{
int length = text1.Length;
@@ -726,6 +1704,7 @@ namespace Lucene.Net.Analysis.Util
return true;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool Equals(string text1, char[] text2)
{
int length = text1.Length;
@@ -763,24 +1742,37 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
/// <param name="obj">Another dictionary to test the values of</param>
/// <returns><c>true</c> if the given object is an <see cref="T:IDictionary{object, V}"/> that contains
- /// the same key value pairs as the current map</returns>
- public override bool Equals(object obj)
+ /// the same text value pairs as the current dictionary</returns>
+ public override bool Equals(object? obj)
{
- var other = obj as IDictionary<string, TValue>;
- if (other is null)
+ if (obj is null)
+ return false;
+ if (obj is not IDictionary<string, TValue> other)
return false;
-
if (this.Count != other.Count)
return false;
- using (var iter = other.GetEnumerator())
+ if (obj is CharArrayDictionary<TValue> charArrayDictionary)
+ {
+ using var iter = charArrayDictionary.GetEnumerator();
+ while (iter.MoveNext())
+ {
+ if (!this.TryGetValue(iter.CurrentKey, out TValue? value))
+ return false;
+
+ if (!JCG.EqualityComparer<TValue>.Default.Equals(value!, iter.Current.Value))
+ return false;
+ }
+ }
+ else
{
+ using var iter = other.GetEnumerator();
while (iter.MoveNext())
{
- if (!this.TryGetValue(iter.Current.Key, out TValue value))
+ if (!this.TryGetValue(iter.Current.Key, out TValue? value))
return false;
- if (!EqualityComparer<TValue>.Default.Equals(value, iter.Current.Value))
+ if (!JCG.EqualityComparer<TValue>.Default.Equals(value!, iter.Current.Value))
return false;
}
}
@@ -797,28 +1789,35 @@ namespace Lucene.Net.Analysis.Util
{
const int PRIME = 31; // arbitrary prime
int hash = PRIME;
- using (var iter = (EntryIterator)EntrySet().GetEnumerator())
+ using (var iter = GetEnumerator())
{
while (iter.MoveNext())
{
- hash = (hash * PRIME) ^ iter.Current.Key.GetHashCode();
- hash = (hash * PRIME) ^ iter.Current.Value.GetHashCode();
+ hash = (hash * PRIME) ^ iter.CurrentKeyString.GetHashCode();
+ TValue? value = iter.CurrentValue;
+ hash = (hash * PRIME) ^ (value is null ? 0 : JCG.EqualityComparer<TValue>.Default.GetHashCode(value));
}
}
return hash;
}
- private int GetHashCode(char[] text, int offset, int length)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private int GetHashCode(char[] text, int startIndex, int length)
{
if (text is null)
- {
- throw new ArgumentNullException(nameof(text), "text can't be null"); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
- }
+ throw new ArgumentNullException(nameof(text)); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (length < 0)
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (startIndex > text.Length - length) // Checks for int overflow
+ throw new ArgumentException(SR.ArgumentOutOfRange_IndexLength);
+
int code = 0;
- int stop = offset + length;
+ int stop = startIndex + length;
if (ignoreCase)
{
- for (int i = offset; i < stop;)
+ for (int i = startIndex; i < stop;)
{
int codePointAt = charUtils.CodePointAt(text, i, stop);
code = code * 31 + Character.ToLower(codePointAt, CultureInfo.InvariantCulture); // LUCENENET specific - need to use invariant culture to match Java
@@ -827,7 +1826,7 @@ namespace Lucene.Net.Analysis.Util
}
else
{
- for (int i = offset; i < stop; i++)
+ for (int i = startIndex; i < stop; i++)
{
code = code * 31 + text[i];
}
@@ -835,12 +1834,11 @@ namespace Lucene.Net.Analysis.Util
return code;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private int GetHashCode(ICharSequence text)
{
- if (text is null)
- {
- throw new ArgumentNullException(nameof(text), "text can't be null"); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
- }
+ if (text is null || !text.HasValue)
+ throw new ArgumentNullException(nameof(text)); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
int code = 0;
int length = text.Length;
@@ -863,12 +1861,11 @@ namespace Lucene.Net.Analysis.Util
return code;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private int GetHashCode(string text)
{
if (text is null)
- {
- throw new ArgumentNullException(nameof(text), "text can't be null"); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
- }
+ throw new ArgumentNullException(nameof(text)); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
int code = 0;
int length = text.Length;
@@ -900,54 +1897,137 @@ namespace Lucene.Net.Analysis.Util
public virtual LuceneVersion MatchVersion => matchVersion;
/// <summary>
- /// Adds a placeholder with the given <paramref name="text"/> as the key.
+ /// Adds a placeholder with the given <paramref name="text"/> as the text.
+ /// Primarily for internal use by <see cref="CharArraySet"/>.
+ /// <para/>
+ /// <b>NOTE:</b> If <c>ignoreCase</c> is <c>true</c> for this <see cref="CharArrayDictionary{TValue}"/>, the text array will be directly modified.
+ /// </summary>
+ /// <param name="text">A key with which the placeholder is associated.</param>
+ /// <param name="startIndex">The position of the <paramref name="text"/> where the target text begins.</param>
+ /// <param name="length">The total length of the <paramref name="text"/>.</param>
+ /// <returns><c>true</c> if the text was added, <c>false</c> if the text already existed.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref name="length"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="startIndex"/> and <paramref name="length"/> refer to a position outside of <paramref name="text"/>.</exception>
+ internal virtual bool Put(char[] text, int startIndex, int length)
+ {
+ return PutImpl(text, startIndex, length, PLACEHOLDER) is null;
+ }
+
+ /// <summary>
+ /// Adds a placeholder with the given <paramref name="text"/> as the text.
/// Primarily for internal use by <see cref="CharArraySet"/>.
+ /// <para/>
+ /// <b>NOTE:</b> If <c>ignoreCase</c> is <c>true</c> for this <see cref="CharArrayDictionary{TValue}"/>, the text array will be directly modified.
+ /// The user should never modify this text array after calling this method.
/// </summary>
- public virtual bool Put(char[] text)
+ /// <returns><c>true</c> if the text was added, <c>false</c> if the text already existed.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ internal virtual bool Put(char[] text)
{
return PutImpl(text, PLACEHOLDER) is null;
}
/// <summary>
- /// Adds a placeholder with the given <paramref name="text"/> as the key.
+ /// Adds a placeholder with the given <paramref name="text"/> as the text.
/// Primarily for internal use by <see cref="CharArraySet"/>.
/// </summary>
- public virtual bool Put(ICharSequence text)
+ /// <returns><c>true</c> if the text was added, <c>false</c> if the text already existed.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="text"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <paramref name="text"/>'s <see cref="ICharSequence.HasValue"/> property returns <c>false</c>.</exception>
+ internal virtual bool Put(ICharSequence text)
{
return PutImpl(text, PLACEHOLDER) is null;
}
/// <summary>
- /// Adds a placeholder with the given <paramref name="text"/> as the key.
+ /// Adds a placeholder with the given <paramref name="text"/> as the text.
/// Primarily for internal use by <see cref="CharArraySet"/>.
/// </summary>
- public virtual bool Put(string text)
+ /// <returns><c>true</c> if the text was added, <c>false</c> if the text already existed.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ internal virtual bool Put(string text)
{
return PutImpl(text, PLACEHOLDER) is null;
}
/// <summary>
- /// Adds a placeholder with the given <paramref name="o"/> as the key.
+ /// Adds a placeholder with the given <paramref name="text"/> as the text.
/// Primarily for internal use by <see cref="CharArraySet"/>.
/// </summary>
- public virtual bool Put(object o)
+ /// <returns><c>true</c> if the text was added, <c>false</c> if the text already existed.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ internal virtual bool Put<T>(T text)
+ {
+ return PutImpl(text, PLACEHOLDER) is null;
+ }
+
+ bool ICharArrayDictionary.Put(char[] text, int startIndex, int length) => Put(text, startIndex, length);
+ bool ICharArrayDictionary.Put(char[] text) => Put(text);
+ bool ICharArrayDictionary.Put(string text) => Put(text);
+ bool ICharArrayDictionary.Put(ICharSequence text) => Put(text);
+ bool ICharArrayDictionary.Put<T>(T text) => Put(text);
+
+ /// <summary>
+ /// Returns a copy of the current <see cref="CharArrayDictionary{TValue}"/> as a new instance of <see cref="CharArrayDictionary{TValue}"/>.
+ /// Preserves the value of <c>matchVersion</c> and <c>ignoreCase</c> from the current instance.
+ /// </summary>
+ /// <returns> A copy of the current <see cref="CharArrayDictionary{TValue}"/> as a <see cref="CharArrayDictionary{TValue}"/>. </returns>
+ // LUCENENET specific - allow .NET-like syntax for copying CharArrayDictionary
+ public virtual CharArrayDictionary<TValue> ToCharArrayDictionary()
+ {
+ return CharArrayDictionary.Copy(this.matchVersion, (IDictionary<string, TValue>)this);
+ }
+
+ /// <summary>
+ /// Returns a copy of the current <see cref="CharArrayDictionary{TValue}"/> as a new instance of <see cref="CharArrayDictionary{TValue}"/>
+ /// using the specified <paramref name="matchVersion"/> value. Preserves the value of <c>ignoreCase</c> from the current instance.
+ /// </summary>
+ /// <param name="matchVersion">
+ /// compatibility match version see <a href="#version">Version
+ /// note</a> above for details. </param>
+ /// <returns> A copy of the current <see cref="CharArrayDictionary{TValue}"/> as a <see cref="CharArrayDictionary{TValue}"/>. </returns>
+ // LUCENENET specific - allow .NET-like syntax for copying CharArrayDictionary
+ public virtual CharArrayDictionary<TValue> ToCharArrayDictionary(LuceneVersion matchVersion)
+ {
+ return CharArrayDictionary.Copy(matchVersion, (IDictionary<string, TValue>)this);
+ }
+
+ /// <summary>
+ /// Returns a copy of the current <see cref="CharArrayDictionary{TValue}"/> as a new instance of <see cref="CharArrayDictionary{TValue}"/>
+ /// using the specified <paramref name="matchVersion"/> and <paramref name="ignoreCase"/> values.
+ /// </summary>
+ /// <param name="matchVersion">
+ /// compatibility match version see <a href="#version">Version
+ /// note</a> above for details. </param>
+ /// <param name="ignoreCase"><c>false</c> if and only if the set should be case sensitive otherwise <c>true</c>.</param>
+ /// <returns> A copy of the current <see cref="CharArrayDictionary{TValue}"/> as a <see cref="CharArrayDictionary{TValue}"/>. </returns>
+ // LUCENENET specific - allow .NET-like syntax for copying CharArrayDictionary
+ public virtual CharArrayDictionary<TValue> ToCharArrayDictionary(LuceneVersion matchVersion, bool ignoreCase)
{
- return PutImpl(o, PLACEHOLDER) is null;
+ return new CharArrayDictionary<TValue>(matchVersion, this, ignoreCase);
}
/// <summary>
- /// Gets the value associated with the specified key.
+ /// Gets the value associated with the specified text.
/// </summary>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="offset">The position of the <paramref name="key"/> where the target key begins.</param>
- /// <param name="length">The total length of the <paramref name="key"/>.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
+ /// <param name="text">The text of the value to get.</param>
+ /// <param name="startIndex">The position of the <paramref name="text"/> where the target text begins.</param>
+ /// <param name="length">The total length of the <paramref name="text"/>.</param>
+ /// <param name="value">When this method returns, contains the value associated with the specified text,
+ /// if the text is found; otherwise, the default value for the type of the value parameter.
/// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- public virtual bool TryGetValue(char[] key, int offset, int length, out TValue value)
+ /// <returns><c>true</c> if the <see cref="CharArrayDictionary{TValue}"/> contains an element with the specified text; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref name="length"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="startIndex"/> and <paramref name="length"/> refer to a position outside of <paramref name="text"/>.</exception>
+ public virtual bool TryGetValue(char[] text, int startIndex, int length, [MaybeNullWhen(returnValue: false)] out TValue value)
{
- var val = values[GetSlot(key, offset, length)];
+ var val = values[GetSlot(text, startIndex, length)];
if (val != null)
{
value = val.Value;
@@ -958,16 +2038,20 @@ namespace Lucene.Net.Analysis.Util
}
/// <summary>
- /// Gets the value associated with the specified key.
+ /// Gets the value associated with the specified text.
/// </summary>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
+ /// <param name="text">The text of the value to get.</param>
+ /// <param name="value">When this method returns, contains the value associated with the specified text,
+ /// if the text is found; otherwise, the default value for the type of the value parameter.
/// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- public virtual bool TryGetValue(char[] key, out TValue value)
+ /// <returns><c>true</c> if the <see cref="CharArrayDictionary{TValue}"/> contains an element with the specified text; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ public virtual bool TryGetValue(char[] text, [MaybeNullWhen(returnValue: false)] out TValue value)
{
- var val = values[GetSlot(key, 0, key.Length)];
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
+ var val = values[GetSlot(text, 0, text.Length)];
if (val != null)
{
value = val.Value;
@@ -978,16 +2062,33 @@ namespace Lucene.Net.Analysis.Util
}
/// <summary>
- /// Gets the value associated with the specified key.
+ /// Gets the value associated with the specified text.
/// </summary>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
+ /// <param name="text">The text of the value to get.</param>
+ /// <param name="value">When this method returns, contains the value associated with the specified text,
+ /// if the text is found; otherwise, the default value for the type of the value parameter.
/// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- public virtual bool TryGetValue(ICharSequence key, out TValue value)
- {
- var val = values[GetSlot(key)];
+ /// <returns><c>true</c> if the <see cref="CharArrayDictionary{TValue}"/> contains an element with the specified text; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="text"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <paramref name="text"/>'s <see cref="ICharSequence.HasValue"/> property returns <c>false</c>.
+ /// </exception>
+ public virtual bool TryGetValue(ICharSequence text, [MaybeNullWhen(returnValue: false)] out TValue value)
+ {
+ if (text is null || !text.HasValue)
+ throw new ArgumentNullException(nameof(text));
+
+ if (text is StringCharSequence strCs)
+ return TryGetValue(strCs.Value!, out value);
+ if (text is CharArrayCharSequence charArrayCs)
+ return TryGetValue(charArrayCs.Value!, out value);
+ if (text is StringBuilderCharSequence stringBuilderCs) // LUCENENET: Indexing into a StringBuilder is slow, so materialize
+ return TryGetValue(stringBuilderCs.Value!.ToString(), out value);
+
+ var val = values[GetSlot(text)];
if (val != null)
{
value = val.Value;
@@ -998,113 +2099,146 @@ namespace Lucene.Net.Analysis.Util
}
/// <summary>
- /// Gets the value associated with the specified key.
+ /// Gets the value associated with the specified text.
/// </summary>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
+ /// <param name="text">The text of the value to get.</param>
+ /// <param name="value">When this method returns, contains the value associated with the specified text,
+ /// if the text is found; otherwise, the default value for the type of the value parameter.
/// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- public virtual bool TryGetValue(string key, out TValue value)
+ /// <returns><c>true</c> if the <see cref="CharArrayDictionary{TValue}"/> contains an element with the specified text; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ public virtual bool TryGetValue(string text, [NotNullWhen(returnValue: false)] out TValue value)
{
- var val = values[GetSlot(key)];
+ var val = values[GetSlot(text)];
if (val != null)
{
- value = val.Value;
+ value = val.Value!;
return true;
}
- value = default;
+ value = default!;
return false;
}
/// <summary>
- /// Gets the value associated with the specified key.
+ /// Gets the value associated with the specified text.
/// </summary>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
+ /// <param name="text">The text of the value to get.</param>
+ /// <param name="value">When this method returns, contains the value associated with the specified text,
+ /// if the text is found; otherwise, the default value for the type of the value parameter.
/// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- public virtual bool TryGetValue(object key, out TValue value)
+ /// <returns><c>true</c> if the <see cref="CharArrayDictionary{TValue}"/> contains an element with the specified text; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ public virtual bool TryGetValue<T>(T text, [MaybeNullWhen(returnValue: false)] out TValue value)
{
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
// LUCENENET NOTE: Testing for *is* is at least 10x faster
// than casting using *as* and then checking for null.
// http://stackoverflow.com/q/1583050/181087
- if (key is char[])
- {
- var text = key as char[];
- return TryGetValue(text, 0, text.Length, out value);
- }
- return TryGetValue(key.ToString(), out value);
+ if (text is string str)
+ return TryGetValue(str, out value);
+ if (text is char[] charArray)
+ return TryGetValue(charArray, 0, charArray.Length, out value);
+ if (text is ICharSequence cs)
+ return TryGetValue(cs, out value);
+
+ var returnType = CharArrayDictionary.ConvertObjectToChars(text, out char[] chars, out string s);
+ if (returnType == CharArrayDictionary.CharReturnType.String)
+ return TryGetValue(s, out value);
+ else
+ return TryGetValue(chars, out value);
}
/// <summary>
- /// Gets or sets the value associated with the specified key.
+ /// Gets or sets the value associated with the specified text.
+ /// <para/>
+ /// <b>Note:</b> If ignoreCase is <c>true</c> for this dictionary, the text array will be directly modified.
/// </summary>
- /// <param name="key">The key of the value to get or set.</param>
- /// <param name="offset">The position of the <paramref name="key"/> where the target key begins.</param>
- /// <param name="length">The total length of the <paramref name="key"/>.</param>
- public virtual TValue this[char[] key, int offset, int length]
+ /// <param name="text">The text of the value to get or set.</param>
+ /// <param name="startIndex">The position of the <paramref name="text"/> where the target text begins.</param>
+ /// <param name="length">The total length of the <paramref name="text"/>.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref name="length"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="startIndex"/> and <paramref name="length"/> refer to a position outside of <paramref name="text"/>.</exception>
+ public virtual TValue this[char[] text, int startIndex, int length]
{
- get => Get(key, offset, length);
- set => Put(key, value);
+ get => Get(text, startIndex, length, throwIfNotFound: true);
+ set => Set(text, startIndex, length, value);
}
/// <summary>
- /// Gets or sets the value associated with the specified key.
+ /// Gets or sets the value associated with the specified text.
+ /// <para/>
+ /// <b>Note:</b> If ignoreCase is <c>true</c> for this dictionary, the text array will be directly modified.
+ /// The user should never modify this text array after calling this setter.
/// </summary>
- /// <param name="key">The key of the value to get or set.</param>
- public virtual TValue this[char[] key]
+ /// <param name="text">The text of the value to get or set.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ public virtual TValue this[char[] text]
{
- get => Get(key);
- set => Put(key, value);
+ get => Get(text, throwIfNotFound: true);
+ set => Set(text, value);
}
/// <summary>
- /// Gets or sets the value associated with the specified key.
+ /// Gets or sets the value associated with the specified text.
/// </summary>
- /// <param name="key">The key of the value to get or set.</param>
- public virtual TValue this[ICharSequence key]
+ /// <param name="text">The text of the value to get or set.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="text"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <paramref name="text"/>'s <see cref="ICharSequence.HasValue"/> property returns <c>false</c>.
+ /// </exception>
+ public virtual TValue this[ICharSequence text]
{
- get => Get(key);
- set => Put(key, value);
+ get => Get(text, throwIfNotFound: true);
+ set => Set(text, value);
}
/// <summary>
- /// Gets or sets the value associated with the specified key.
+ /// Gets or sets the value associated with the specified text.
/// </summary>
- /// <param name="key">The key of the value to get or set.</param>
- public virtual TValue this[string key]
+ /// <param name="text">The text of the value to get or set.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ public virtual TValue this[string text]
{
- get => Get(key);
- set => Put(key, value);
+ get => Get(text, throwIfNotFound: true);
+ set => Set(text, value);
}
/// <summary>
- /// Gets or sets the value associated with the specified key.
+ /// Gets or sets the value associated with the specified text.
/// </summary>
- /// <param name="key">The key of the value to get or set.</param>
- public virtual TValue this[object key]
+ /// <param name="text">The text of the value to get or set.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ public virtual TValue this[object text]
{
- get => Get(key);
- set => Put(key, value);
+ get => Get(text, throwIfNotFound: true);
+ set => Set(text, value);
}
/// <summary>
- /// Gets a collection containing the keys in the <see cref="CharArrayMap{TValue}"/>.
+ /// Gets a collection containing the keys in the <see cref="CharArrayDictionary{TValue}"/>.
/// </summary>
- public virtual ICollection<string> Keys => KeySet;
+ public virtual CharArraySet Keys => KeySet;
+
+ ICollection<string> IDictionary<string, TValue>.Keys => KeySet;
+
+ IEnumerable<string> IReadOnlyDictionary<string, TValue>.Keys => KeySet;
- private volatile ICollection<TValue> valueSet;
+ private volatile ValueCollection? valueSet;
/// <summary>
- /// Gets a collection containing the values in the <see cref="CharArrayMap{TValue}"/>.
+ /// Gets a collection containing the values in the <see cref="CharArrayDictionary{TValue}"/>.
/// This specialized collection can be enumerated in order to read its values and
/// overrides <see cref="object.ToString()"/> in order to display a string
/// representation of the values.
/// </summary>
- public ICollection<TValue> Values
+ public ValueCollection Values
{
get
{
@@ -1116,159 +2250,172 @@ namespace Lucene.Net.Analysis.Util
}
}
- /// <summary>
- /// LUCENENET specific class used to break the infinite recursion when the
- /// CharArraySet iterates the keys of this dictionary via <see cref="OriginalKeySet"/>.
- /// In Java, the keyset of the abstract base class was used to break the infinite recursion,
- /// however this class doesn't have an abstract base class so that is not an option.
- /// This class is just a facade around the keys (not another collection of keys), so it
- /// doesn't consume any additional RAM while providing another "virtual" collection to iterate over.
- /// </summary>
- internal class KeyCollection : ICollection<string>
- {
- private readonly CharArrayMap<TValue> outerInstance;
+ ICollection<TValue> IDictionary<string, TValue>.Values => Values;
- public KeyCollection(CharArrayMap<TValue> outerInstance)
- {
- this.outerInstance = outerInstance;
- }
+ IEnumerable<TValue> IReadOnlyDictionary<string, TValue>.Values => Values;
- public int Count => outerInstance.Count;
+ #region Nested Class: ValueCollection
- public bool IsReadOnly => outerInstance.IsReadOnly;
+ /// <summary>
+ /// Class that represents the values in the <see cref="CharArrayDictionary{TValue}"/>.
+ /// </summary>
+ // LUCENENET specific
+ [DebuggerDisplay("Count = {Count}, Values = {ToString()}")]
+ public sealed class ValueCollection : ICollection<TValue>, ICollection, IReadOnlyCollection<TValue>
+ {
+ private readonly CharArrayDictionary<TValue> dictionary;
- public void Add(string item) // LUCENENET TODO: API - make an explicit implementation that isn't public
+ /// <summary>
+ /// Initializes a new instance of <see cref="ValueCollection"/> for the provided <see cref="CharArrayDictionary{TValue}"/>.
+ /// </summary>
+ /// <param name="dictionary">The dictionary to read the values from.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="dictionary"/> is <c>null</c>.</exception>
+ public ValueCollection(CharArrayDictionary<TValue> dictionary)
{
- throw UnsupportedOperationException.Create();
+ this.dictionary = dictionary ?? throw new ArgumentNullException(nameof(dictionary));
}
- public void Clear()
- {
- outerInstance.Clear();
- }
+ /// <summary>
+ /// Gets the number of elements contained in the <see cref="ValueCollection"/>.
+ /// </summary>
+ /// <remarks>
+ /// Retrieving the value of this property is an O(1) operation.
+ /// </remarks>
+ public int Count => dictionary.Count;
- public bool Contains(string item)
- {
- return outerInstance.ContainsKey(item);
- }
+ bool ICollection<TValue>.IsReadOnly => true;
- public void CopyTo(string[] array, int arrayIndex)
- {
- using var iter = GetEnumerator();
- for (int i = arrayIndex; iter.MoveNext(); i++)
- {
- array[i] = iter.Current;
- }
- }
+ bool ICollection.IsSynchronized => false;
- public IEnumerator<string> GetEnumerator()
- {
- return new KeyEnumerator(outerInstance);
- }
+ object ICollection.SyncRoot => ((ICollection)dictionary).SyncRoot;
- public bool Remove(string item) // LUCENENET TODO: API - make an explicit implementation that isn't public
+ void ICollection<TValue>.Add(TValue item)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ValueCollectionSet);
}
- IEnumerator IEnumerable.GetEnumerator()
+ void ICollection<TValue>.Clear()
{
- return GetEnumerator();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ValueCollectionSet);
}
/// <summary>
- /// LUCENENET specific class to iterate the values in the <see cref="KeyCollection"/>.
+ /// Determines whether the set contains a specific element.
/// </summary>
- private class KeyEnumerator : IEnumerator<string>
+ /// <param name="item">The element to locate in the set.</param>
+ /// <returns><c>true</c> if the set contains item; otherwise, <c>false</c>.</returns>
+ [SuppressMessage("Style", "IDE0002:Name can be simplified", Justification = "This is a false warning.")]
+ public bool Contains(TValue item)
{
- private readonly EntryIterator entryIterator;
-
- public KeyEnumerator(CharArrayMap<TValue> outerInstance)
- {
- this.entryIterator = new EntryIterator(outerInstance, !outerInstance.IsReadOnly);
- }
-
- public string Current => entryIterator.Current.Key;
-
- object IEnumerator.Current => Current;
-
- public void Dispose()
- {
- // nothing to do
- }
-
- public bool MoveNext()
+ for (int i = 0; i < dictionary.values.Length; i++)
{
- return entryIterator.MoveNext();
+ var value = dictionary.values[i];
+ if (JCG.EqualityComparer<TValue>.Equals(value, item))
+ return true;
}
+ return false;
+ }
- public void Reset()
+ /// <summary>
+ /// Copies the <see cref="ValueCollection"/> elements to an existing one-dimensional
+ /// array, starting at the specified array index.
+ /// </summary>
+ /// <param name="array">The one-dimensional array that is the destination of the elements copied from
+ /// the <see cref="ValueCollection"/>. The array must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than 0.</exception>
+ /// <exception cref="ArgumentException">The number of elements in the source <see cref="ValueCollection"/>
+ /// is greater than the available space from <paramref name="index"/> to the end of the destination
+ /// <paramref name="array"/>.</exception>
+ /// <remarks>
+ /// The elements are copied to the array in the same order in which the enumerator iterates through the
+ /// <see cref="ValueCollection"/>.
+ /// <para/>
+ /// This method is an O(<c>n</c>) operation, where <c>n</c> is <see cref="Count"/>.
+ /// </remarks>
+ public void CopyTo(TValue[] array, int index)
+ {
+ if (array is null)
+ throw new ArgumentNullException(nameof(array));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (index > array.Length || dictionary.Count > array.Length - index)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+
+ foreach (var entry in this)
+ array[index++] = entry!;
+ }
+
+ void ICollection.CopyTo(Array array, int index)
+ {
+ if (array is null)
+ throw new ArgumentNullException(nameof(array));
+ if (array.Rank != 1)
+ throw new ArgumentException(SR.Arg_RankMultiDimNotSupported, nameof(array));
+ if (array.GetLowerBound(0) != 0)
+ throw new ArgumentException(SR.Arg_NonZeroLowerBound, nameof(array));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (array.Length - index < dictionary.Count)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+
+ if (array is TValue[] values)
{
- entryIterator.Reset();
+ CopyTo(values, index);
}
- }
- }
-
- /// <summary>
- /// LUCENENET specific class that represents the values in the <see cref="CharArrayMap{TValue}"/>.
- /// </summary>
- internal class ValueCollection : ICollection<TValue>
- {
- private readonly CharArrayMap<TValue> outerInstance;
-
- public ValueCollection(CharArrayMap<TValue> outerInstance)
- {
- this.outerInstance = outerInstance;
- }
-
- public int Count => outerInstance.Count;
-
- public bool IsReadOnly => outerInstance.IsReadOnly;
-
- public void Add(TValue item) // LUCENENET TODO: API - make an explicit implementation that isn't public
- {
- throw UnsupportedOperationException.Create();
- }
-
- public void Clear()
- {
- outerInstance.Clear();
- }
-
- public bool Contains(TValue item)
- {
- for (int i = 0; i < outerInstance.values.Length; i++)
+ else
{
- var value = outerInstance.values[i];
- if (J2N.Collections.Generic.EqualityComparer<TValue>.Equals(value, item))
- return true;
+ try
+ {
+ object?[] objects = (object?[])array;
+ foreach (var entry in this)
+ objects[index++] = entry;
+ }
+ catch (ArrayTypeMismatchException)
+ {
+ throw new ArgumentException(SR.Argument_InvalidArrayType, nameof(array));
+ }
}
- return false;
}
- public void CopyTo(TValue[] array, int arrayIndex) // LUCENENET TODO: API - make an explicit implementation that isn't public
+ /// <summary>
+ /// Returns an enumerator that iterates through the <see cref="ValueCollection"/>.
+ /// </summary>
+ /// <returns>An enumerator that iterates through the <see cref="ValueCollection"/>.</returns>
+ /// <remarks>
+ /// An enumerator remains valid as long as the collection remains unchanged. If changes are made to
+ /// the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably
+ /// invalidated and the next call to <see cref="Enumerator.MoveNext()"/> or <see cref="IEnumerator.Reset()"/>
+ /// throws an <see cref="InvalidOperationException"/>.
+ /// <para/>
+ /// This method is an <c>O(log n)</c> operation.
+ /// </remarks>
+ public Enumerator GetEnumerator()
{
- throw UnsupportedOperationException.Create();
+ return new Enumerator(dictionary);
}
- public IEnumerator<TValue> GetEnumerator()
- {
- return new ValueEnumerator(outerInstance);
- }
+ IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() => GetEnumerator();
- public bool Remove(TValue item) // LUCENENET TODO: API - make an explicit implementation that isn't public
- {
- throw UnsupportedOperationException.Create();
- }
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
- IEnumerator IEnumerable.GetEnumerator()
+ bool ICollection<TValue>.Remove(TValue item)
{
- return GetEnumerator();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ValueCollectionSet);
}
+ /// <summary>
+ /// Returns a string that represents the current collection.
+ /// <para/>
+ /// The presentation has a specific format. It is enclosed by square
+ /// brackets ("[]"). Elements are separated by ', ' (comma and space).
+ /// <c>null</c> values are represented as the string "null".
+ /// </summary>
+ /// <returns>A string that represents the current collection.</returns>
public override string ToString()
{
- using var i = (ValueEnumerator)GetEnumerator();
+ using var i = GetEnumerator();
if (!i.HasNext)
return "[]";
@@ -1276,93 +2423,348 @@ namespace Lucene.Net.Analysis.Util
sb.Append('[');
while (i.MoveNext())
{
- TValue value = i.Current;
+ TValue? value = i.Current;
if (sb.Length > 1)
{
sb.Append(',').Append(' ');
}
- sb.Append(value.ToString());
+ if (value is not null)
+ sb.Append(value.ToString());
+ else
+ sb.Append("null");
}
return sb.Append(']').ToString();
}
+ #region Nested Struct: Enumerator
+
/// <summary>
- /// LUCENENET specific class to enumerate the values in the <see cref="ValueCollection"/>.
+ /// Enumerates the elements of a <see cref="ValueCollection"/>.
/// </summary>
- private class ValueEnumerator : IEnumerator<TValue>
- {
- private readonly EntryIterator entryIterator;
-
- public ValueEnumerator(CharArrayMap<TValue> outerInstance)
+ /// <remarks>
+ /// The <c>foreach</c> statement of the C# language (<c>for each</c> in C++, <c>For Each</c> in Visual Basic)
+ /// hides the complexity of enumerators. Therefore, using <c>foreach</c> is recommended instead of directly manipulating the enumerator.
+ /// <para/>
+ /// Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying collection.
+ /// <para/>
+ /// Initially, the enumerator is positioned before the first element in the collection. At this position, the
+ /// <see cref="Current"/> property is undefined. Therefore, you must call the
+ /// <see cref="MoveNext()"/> method to advance the enumerator to the first element
+ /// of the collection before reading the value of <see cref="Current"/>.
+ /// <para/>
+ /// The <see cref="Current"/> property returns the same object until
+ /// <see cref="MoveNext()"/> is called. <see cref="MoveNext()"/>
+ /// sets <see cref="Current"/> to the next element.
+ /// <para/>
+ /// If <see cref="MoveNext()"/> passes the end of the collection, the enumerator is
+ /// positioned after the last element in the collection and <see cref="MoveNext()"/>
+ /// returns <c>false</c>. When the enumerator is at this position, subsequent calls to <see cref="MoveNext()"/>
+ /// also return <c>false</c>. If the last call to <see cref="MoveNext()"/> returned <c>false</c>,
+ /// <see cref="Current"/> is undefined. You cannot set <see cref="Current"/>
+ /// to the first element of the collection again; you must create a new enumerator object instead.
+ /// <para/>
+ /// An enumerator remains valid as long as the collection remains unchanged. If changes are made to the collection,
+ /// such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and the next call
+ /// to <see cref="MoveNext()"/> or <see cref="IEnumerator.Reset()"/> throws an
+ /// <see cref="InvalidOperationException"/>.
+ /// <para/>
+ /// The enumerator does not have exclusive access to the collection; therefore, enumerating through a collection is
+ /// intrinsically not a thread-safe procedure. To guarantee thread safety during enumeration, you can lock the
+ /// collection during the entire enumeration. To allow the collection to be accessed by multiple threads for
+ /// reading and writing, you must implement your own synchronization.
+ /// </remarks>
+ // LUCENENET specific
+ public readonly struct Enumerator : IEnumerator<TValue>, IEnumerator
+ {
+ private readonly CharArrayDictionary<TValue>.Enumerator entryIterator;
+
+ internal Enumerator(CharArrayDictionary<TValue> dictionary) // LUCENENET specific - marked internal to match .NET collections
{
- this.entryIterator = new EntryIterator(outerInstance, !outerInstance.IsReadOnly);
+ this.entryIterator = dictionary.GetEnumerator();
}
- public TValue Current => entryIterator.CurrentValue;
-
- object IEnumerator.Current => Current;
-
+ /// <summary>
+ /// Gets the element at the current position of the enumerator.
+ /// </summary>
+ /// <remarks>
+ /// <see cref="Current"/> is undefined under any of the following conditions:
+ /// <list type="bullet">
+ /// <item><description>
+ /// The enumerator is positioned before the first element of the collection. That happens after an
+ /// enumerator is created or after the <see cref="IEnumerator.Reset()"/> method is called. The <see cref="MoveNext()"/>
+ /// method must be called to advance the enumerator to the first element of the collection before reading the value of
+ /// the <see cref="Current"/> property.
+ /// </description></item>
+ /// <item><description>
+ /// The last call to <see cref="MoveNext()"/> returned <c>false</c>, which indicates the end of the collection and that the
+ /// enumerator is positioned after the last element of the collection.
+ /// </description></item>
+ /// <item><description>
+ /// The enumerator is invalidated due to changes made in the collection, such as adding, modifying, or deleting elements.
+ /// </description></item>
+ /// </list>
+ /// <para/>
+ /// <see cref="Current"/> does not move the position of the enumerator, and consecutive calls to <see cref="Current"/> return
+ /// the same object until either <see cref="MoveNext()"/> or <see cref="IEnumerator.Reset()"/> is called.
+ /// </remarks>
+ public TValue Current => entryIterator.CurrentValue!;
+
+ object IEnumerator.Current => entryIterator.CurrentValue!;
+
+ /// <summary>
+ /// Releases all resources used by the <see cref="Enumerator"/>.
+ /// </summary>
public void Dispose()
{
entryIterator.Dispose();
}
+ /// <summary>
+ /// Advances the enumerator to the next element of the <see cref="ValueCollection"/>.
+ /// </summary>
+ /// <returns><c>true</c> if the enumerator was successfully advanced to the next element;
+ /// <c>false</c> if the enumerator has passed the end of the collection.</returns>
+ /// <exception cref="InvalidOperationException">The collection was modified after the enumerator was created.</exception>
+ /// <remarks>
+ /// After an enumerator is created, the enumerator is positioned before the first element in the collection,
+ /// and the first call to the <see cref="MoveNext()"/> method advances the enumerator to the first element
+ /// of the collection.
+ /// <para/>
+ /// If MoveNext passes the end of the collection, the enumerator is positioned after the last element in the
+ /// collection and <see cref="MoveNext()"/> returns <c>false</c>. When the enumerator is at this position,
+ /// subsequent calls to <see cref="MoveNext()"/> also return <c>false</c>.
+ /// <para/>
+ /// An enumerator remains valid as long as the collection remains unchanged. If changes are made to the
+ /// collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated
+ /// and the next call to <see cref="MoveNext()"/> or <see cref="IEnumerator.Reset()"/> throws an
+ /// <see cref="InvalidOperationException"/>.
+ /// </remarks>
public bool MoveNext()
{
return entryIterator.MoveNext();
}
- public void Reset()
+ private void Reset()
{
- entryIterator.Reset();
+ ((IEnumerator)entryIterator).Reset();
}
- public bool HasNext => entryIterator.HasNext;
+ void IEnumerator.Reset() => Reset();
+
+ internal bool HasNext => entryIterator.HasNext;
}
+
+ #endregion
}
- #endregion
+ #endregion Nested Class: ValueCollection
/// <summary>
- /// <c>true</c> if the <see cref="CharArrayMap{TValue}"/> is read-only; otherwise <c>false</c>.
+ /// <c>true</c> if the <see cref="CharArrayDictionary{TValue}"/> is read-only; otherwise <c>false</c>.
/// </summary>
- public virtual bool IsReadOnly { get; private set; }
+ public virtual bool IsReadOnly => false;
+
+ #endregion For .NET Support LUCENENET
/// <summary>
- /// Returns an enumerator that iterates through the <see cref="CharArrayMap{TValue}"/>.
+ /// Returns an enumerator that iterates through the <see cref="CharArrayDictionary{TValue}"/>.
/// </summary>
- public virtual IEnumerator<KeyValuePair<string, TValue>> GetEnumerator()
+ /// <returns>A <see cref="CharArrayDictionary{TValue}.Enumerator"/> for the
+ /// <see cref="CharArrayDictionary{TValue}"/>.</returns>
+ /// <remarks>
+ /// For purposes of enumeration, each item is a <see cref="KeyValuePair{TKey, TValue}"/> structure
+ /// representing a value and its text. There are also properties allowing direct access
+ /// to the <see cref="T:char[]"/> array of each element and quick conversions to <see cref="string"/> or <see cref="ICharSequence"/>.
+ /// <para/>
+ /// The <c>foreach</c> statement of the C# language (<c>for each</c> in C++, <c>For Each</c> in Visual Basic)
+ /// hides the complexity of enumerators. Therefore, using <c>foreach</c> is recommended instead of directly manipulating the enumerator.
+ /// <para/>
+ /// This enumerator can be used to read the data in the collection, or modify the corresponding value at the current position.
+ /// <para/>
+ /// Initially, the enumerator is positioned before the first element in the collection. At this position, the
+ /// <see cref="Enumerator.Current"/> property is undefined. Therefore, you must call the
+ /// <see cref="Enumerator.MoveNext()"/> method to advance the enumerator to the first element
+ /// of the collection before reading the value of <see cref="Enumerator.Current"/>.
+ /// <para/>
+ /// The <see cref="Enumerator.Current"/> property returns the same object until
+ /// <see cref="Enumerator.MoveNext()"/> is called. <see cref="Enumerator.MoveNext()"/>
+ /// sets <see cref="Enumerator.Current"/> to the next element.
+ /// <para/>
+ /// If <see cref="Enumerator.MoveNext()"/> passes the end of the collection, the enumerator is
+ /// positioned after the last element in the collection and <see cref="Enumerator.MoveNext()"/>
+ /// returns <c>false</c>. When the enumerator is at this position, subsequent calls to <see cref="Enumerator.MoveNext()"/>
+ /// also return <c>false</c>. If the last call to <see cref="Enumerator.MoveNext()"/> returned <c>false</c>,
+ /// <see cref="Enumerator.Current"/> is undefined. You cannot set <see cref="Enumerator.Current"/>
+ /// to the first element of the collection again; you must create a new enumerator object instead.
+ /// <para/>
+ /// An enumerator remains valid as long as the collection remains unchanged. If changes are made to the collection,
+ /// such as adding, modifying, or deleting elements (other than through the <see cref="Enumerator.SetValue(TValue)"/> method),
+ /// the enumerator is irrecoverably invalidated and the next call
+ /// to <see cref="Enumerator.MoveNext()"/> or <see cref="IEnumerator.Reset()"/> throws an
+ /// <see cref="InvalidOperationException"/>.
+ /// <para/>
+ /// The enumerator does not have exclusive access to the collection; therefore, enumerating through a collection is
+ /// intrinsically not a thread-safe procedure. To guarantee thread safety during enumeration, you can lock the
+ /// collection during the entire enumeration. To allow the collection to be accessed by multiple threads for
+ /// reading and writing, you must implement your own synchronization.
+ /// <para/>
+ /// Default implementations of collections in the <see cref="J2N.Collections.Generic"/> namespace are not synchronized.
+ /// <para/>
+ /// This method is an O(1) operation.
+ /// </remarks>
+ public Enumerator GetEnumerator()
{
- return new EntryIterator(this, false);
+ return new Enumerator(this, Enumerator.KeyValuePair);
}
- /// <summary>
- /// Returns an enumerator that iterates through the <see cref="CharArrayMap{TValue}"/>.
- /// </summary>
- IEnumerator IEnumerable.GetEnumerator()
+ IEnumerator<KeyValuePair<string, TValue>> IEnumerable<KeyValuePair<string, TValue>>.GetEnumerator() => GetEnumerator();
+
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+
+ ICharArrayDictionaryEnumerator ICharArrayDictionary.GetEnumerator() => GetEnumerator();
+
+ IDictionaryEnumerator IDictionary.GetEnumerator()
+ {
+ return new Enumerator(this, Enumerator.DictEntry);
+ }
+
+ void IDictionary.Remove(object key)
{
- return GetEnumerator();
+ throw UnsupportedOperationException.Create();
}
- [Obsolete("Not applicable in this class.")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
- public virtual bool Remove(string key) // LUCENENET TODO: API - make an explicit implementation that isn't public
+ bool IDictionary<string, TValue>.Remove(string key)
{
throw UnsupportedOperationException.Create();
}
- [Obsolete("Not applicable in this class.")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
- public virtual bool Remove(KeyValuePair<string, TValue> item) // LUCENENET TODO: API - make an explicit implementation that isn't public
+ bool ICollection<KeyValuePair<string, TValue>>.Remove(KeyValuePair<string, TValue> item)
{
throw UnsupportedOperationException.Create();
}
+ void ICollection.CopyTo(Array array, int index)
+ {
+ if (array is null)
+ throw new ArgumentNullException(nameof(array));
+ if (array.Rank != 1)
+ throw new ArgumentException(SR.Arg_RankMultiDimNotSupported);
+ if (array.GetLowerBound(0) != 0)
+ throw new ArgumentException(SR.Arg_NonZeroLowerBound);
+ if (index < 0 || index > array.Length)
+ throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (array.Length - index < Count)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+
+ if (array is KeyValuePair<string, TValue>[] strings)
+ {
+ CopyTo(strings, index);
+ }
+ else if (array is KeyValuePair<char[], TValue>[] chars)
+ {
+ CopyTo(chars, index);
+ }
+ else if (array is KeyValuePair<ICharSequence, TValue>[] charSequences)
+ {
+ CopyTo(charSequences, index);
+ }
+ else if (array is DictionaryEntry[] dictEntryArray)
+ {
+ foreach (var item in this)
+ dictEntryArray[index++] = new DictionaryEntry(item.Key, item.Value);
+ }
+ else
+ {
+ if (!(array is object[] objects))
+ {
+ throw new ArgumentException(SR.Argument_InvalidArrayType);
+ }
+ try
+ {
+ foreach (var item in this)
+ objects[index++] = item;
+ }
+ catch (ArrayTypeMismatchException)
+ {
+ throw new ArgumentException(SR.Argument_InvalidArrayType);
+ }
+ }
+ }
+
+ bool IDictionary.IsFixedSize => false;
+
+ bool IDictionary.IsReadOnly => IsReadOnly;
+
+ ICollection IDictionary.Keys => Keys;
+
+ ICollection IDictionary.Values => Values;
+
+ bool ICollection.IsSynchronized => false;
+
+ object ICollection.SyncRoot => this;
+
+ object? IDictionary.this[object key]
+ {
+ get => Get(key, throwIfNotFound: false);
+ set
+ {
+ if (key is null)
+ throw new ArgumentNullException(nameof(key));
+
+ if (value is null && default(TValue) != null)
+ throw new ArgumentNullException(nameof(value));
+
+ TValue val;
+ try
+ {
+ val = (TValue)value!;
+ }
+ catch (InvalidCastException)
+ {
+ throw new ArgumentException(string.Format(SR.Arg_WrongType, value, typeof(TValue)), nameof(value));
+ }
+ var returnType = CharArrayDictionary.ConvertObjectToChars(key, out char[] chars, out string s);
+ if (returnType == CharArrayDictionary.CharReturnType.String)
+ {
+ Set(s, val);
+ }
+ else
+ {
+ Set(chars, val);
+ }
+ }
+ }
+
+ void IDictionary.Add(object key, object? value)
+ {
+ if (key is null)
+ throw new ArgumentNullException(nameof(key));
+
+ TValue val;
+ try
+ {
+ val = (TValue)value!;
+ }
+ catch (InvalidCastException)
+ {
+ throw new ArgumentException(string.Format(SR.Arg_WrongType, value, typeof(TValue)), nameof(value));
+ }
+ var returnType = CharArrayDictionary.ConvertObjectToChars(key, out char[] chars, out string s);
+ if (returnType == CharArrayDictionary.CharReturnType.String)
+ {
+ Add(s, val);
+ }
+ else
+ {
+ Add(chars, val);
+ }
+ }
+
+ bool IDictionary.Contains(object key) => ContainsKey(key);
+
/// <summary>
- /// Gets the number of key/value pairs contained in the <see cref="CharArrayMap{TValue}"/>.
+ /// Gets the number of text/value pairs contained in the <see cref="CharArrayDictionary{TValue}"/>.
/// </summary>
public virtual int Count => count;
@@ -1371,67 +2773,44 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
public override string ToString()
{
+ if (count == 0)
+ return "{}";
+
var sb = new StringBuilder("{");
using (var iter1 = this.GetEnumerator())
{
while (iter1.MoveNext())
{
- KeyValuePair<string, TValue> entry = iter1.Current;
if (sb.Length > 1)
{
sb.Append(", ");
}
- sb.Append(entry.Key);
+ sb.Append(iter1.CurrentKey);
sb.Append('=');
- sb.Append(entry.Value);
+ if (iter1.CurrentValue is not null)
+ sb.Append(iter1.CurrentValue);
+ else
+ sb.Append("null");
}
}
return sb.Append('}').ToString();
}
- private EntrySet_ entrySet = null;
- private CharArraySet keySet = null;
- private KeyCollection originalKeySet = null;
+
- internal virtual EntrySet_ CreateEntrySet()
- {
- return new EntrySet_(this, true);
- }
+ // LUCENENET: Removed entrySet because in .NET we use the collection itself as the IEnumerable
+ private CharArraySet? keySet = null;
- // LUCENENET NOTE: This MUST be a method, since there is an
- // extension method that this class needs to override the behavior of.
- public EntrySet_ EntrySet()
- {
- if (entrySet is null)
- {
- entrySet = CreateEntrySet();
- }
- return entrySet;
- }
+ // LUCENENET: Removed entrySet(), createEntrySet() because in .NET we use the collection itself as the IEnumerable
- /// <summary>
- /// helper for <see cref="CharArraySet"/> to not produce endless recursion
- /// </summary>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
- public ICollection<string> OriginalKeySet
- {
- get
- {
- if (originalKeySet is null)
- {
- // prevent adding of entries
- originalKeySet = new KeyCollection(this);
- }
- return originalKeySet;
- }
- }
+ // LUCENENET: Removed originalKeySet() because we fixed infinite recursion
+ // by adding a custom enumerator for KeyCollection.
/// <summary>
- /// Returns an <see cref="CharArraySet"/> view on the map's keys.
- /// The set will use the same <see cref="matchVersion"/> as this map.
+ /// Returns an <see cref="CharArraySet"/> view on the dictionary's keys.
+ /// The set will use the same <see cref="matchVersion"/> as this dictionary.
/// </summary>
private CharArraySet KeySet
{
@@ -1440,1529 +2819,1065 @@ namespace Lucene.Net.Analysis.Util
if (keySet is null)
{
// prevent adding of entries
- keySet = new UnmodifiableCharArraySet(this);
+ keySet = new KeyCollection(this);
}
return keySet;
}
}
- private sealed class UnmodifiableCharArraySet : CharArraySet
+ #region Nested Class: KeyCollection
+
+ // LUCENENET: This was an anonymous class in Java
+ [DebuggerDisplay("Count = {Count}, Values = {ToString()}")]
+ private sealed class KeyCollection : CharArraySet
{
- internal UnmodifiableCharArraySet(ICharArrayMap map)
+ internal KeyCollection(CharArrayDictionary<TValue> map)
: base(map)
{
}
- public override bool Add(object o) // LUCENENET TODO: API - make an explicit implementation that isn't public
+ public override bool IsReadOnly => true;
+
+ public override bool Add<T>(T text)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_KeyCollectionSet);
}
- public override bool Add(ICharSequence text) // LUCENENET TODO: API - make an explicit implementation that isn't public
+ public override bool Add(ICharSequence text)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_KeyCollectionSet);
}
- public override bool Add(string text) // LUCENENET TODO: API - make an explicit implementation that isn't public
+ public override bool Add(string text)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_KeyCollectionSet);
}
- public override bool Add(char[] text) // LUCENENET TODO: API - make an explicit implementation that isn't public
+ public override bool Add(char[] text)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_KeyCollectionSet);
}
}
+ #endregion Nested Class: KeyCollection
+
+ #region Nested Class: Enumerator
+
/// <summary>
- /// public iterator class so efficient methods are exposed to users
+ /// Enumerates the elements of a <see cref="CharArrayDictionary{TValue}"/>.
+ /// <para/>
+ /// This enumerator exposes <see cref="CurrentKey"/> efficient access to the
+ /// underlying <see cref="T:char[]"/>. It also has <see cref="CurrentKeyString"/>,
+ /// <see cref="CurrentKeyCharSequence"/>, and <see cref="CurrentValue"/> properties for
+ /// convenience.
/// </summary>
- public class EntryIterator : IEnumerator<KeyValuePair<string, TValue>>
+ /// <remarks>
+ /// The <c>foreach</c> statement of the C# language (<c>for each</c> in C++, <c>For Each</c> in Visual Basic)
+ /// hides the complexity of enumerators. Therefore, using <c>foreach</c> is recommended instead of directly manipulating the enumerator.
+ /// <para/>
+ /// This enumerator can be used to read the data in the collection, or modify the corresponding value at the current position.
+ /// <para/>
+ /// Initially, the enumerator is positioned before the first element in the collection. At this position, the
+ /// <see cref="Current"/> property is undefined. Therefore, you must call the
+ /// <see cref="MoveNext()"/> method to advance the enumerator to the first element
+ /// of the collection before reading the value of <see cref="Current"/>.
+ /// <para/>
+ /// The <see cref="Current"/> property returns the same object until
+ /// <see cref="MoveNext()"/> is called. <see cref="MoveNext()"/>
+ /// sets <see cref="Current"/> to the next element.
+ /// <para/>
+ /// If <see cref="MoveNext()"/> passes the end of the collection, the enumerator is
+ /// positioned after the last element in the collection and <see cref="MoveNext()"/>
+ /// returns <c>false</c>. When the enumerator is at this position, subsequent calls to <see cref="MoveNext()"/>
+ /// also return <c>false</c>. If the last call to <see cref="MoveNext()"/> returned <c>false</c>,
+ /// <see cref="Current"/> is undefined. You cannot set <see cref="Current"/>
+ /// to the first element of the collection again; you must create a new enumerator object instead.
+ /// <para/>
+ /// An enumerator remains valid as long as the collection remains unchanged. If changes are made to the collection,
+ /// such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and the next call
+ /// to <see cref="MoveNext()"/> or <see cref="IEnumerator.Reset()"/> throws an
+ /// <see cref="InvalidOperationException"/>.
+ /// <para/>
+ /// The enumerator does not have exclusive access to the collection; therefore, enumerating through a collection is
+ /// intrinsically not a thread-safe procedure. To guarantee thread safety during enumeration, you can lock the
+ /// collection during the entire enumeration. To allow the collection to be accessed by multiple threads for
+ /// reading and writing, you must implement your own synchronization.
+ /// </remarks>
+ // LUCENENET: An attempt was made to make this into a struct, but since it has mutable state that didn't work. So, this should remain a class.
+ public sealed class Enumerator : IEnumerator<KeyValuePair<string, TValue>>, IDictionaryEnumerator, ICharArrayDictionaryEnumerator
{
- private readonly CharArrayMap<TValue> outerInstance;
+ private readonly CharArrayDictionary<TValue> dictionary;
+ private readonly int getEnumeratorRetType; // What should Enumerator.Current return?
+
+ internal const int KeyValuePair = 1;
+ internal const int DictEntry = 2;
internal int pos = -1;
internal int lastPos;
internal readonly bool allowModify;
- internal EntryIterator(CharArrayMap<TValue> outerInstance, bool allowModify)
+ private int version; // LUCENENET specific - track when the enumerator is broken by mutating the state of the original collection
+ private bool notStartedOrEnded; // LUCENENET specific
+
+ internal Enumerator(CharArrayDictionary<TValue> dictionary, int getEnumeratorRetType)
{
- this.outerInstance = outerInstance;
- this.allowModify = allowModify;
+ this.dictionary = dictionary;
+ this.getEnumeratorRetType = getEnumeratorRetType;
+ this.version = dictionary.version;
+ this.allowModify = !dictionary.IsReadOnly;
+ this.notStartedOrEnded = true;
GoNext();
}
- internal void GoNext()
+ private void GoNext()
{
lastPos = pos;
pos++;
- while (pos < outerInstance.keys.Length && outerInstance.keys[pos] is null)
+ while (pos < dictionary.keys.Length && dictionary.keys[pos] is null)
{
pos++;
}
}
- public virtual bool HasNext => pos < outerInstance.keys.Length;
+ internal bool HasNext => pos < dictionary.keys.Length;
/// <summary>
- /// gets the next key... do not modify the returned char[]
+ /// Gets the current text as a <see cref="CharArrayCharSequence"/>.
/// </summary>
- public virtual char[] NextKey()
+ // LUCENENET specific - quick access to ICharSequence interface
+ public ICharSequence CurrentKeyCharSequence
{
- GoNext();
- return outerInstance.keys[lastPos];
+ get
+ {
+ if (notStartedOrEnded)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+
+ char[] key = dictionary.keys[lastPos];
+ if (key is null)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ return key.AsCharSequence();
+ }
}
/// <summary>
- /// gets the next key as a newly created <see cref="string"/> object
+ /// Gets the current text... do not modify the returned char[].
/// </summary>
- public virtual string NextKeyString()
+ [SuppressMessage("Microsoft.Performance", "CA1819", Justification = "Lucene's design requires some writable array properties")]
+ [WritableArray]
+ public char[] CurrentKey
{
- return new string(NextKey());
+ get
+ {
+ if (notStartedOrEnded)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+
+ char[] key = dictionary.keys[lastPos];
+ if (key is null)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ return key;
+ }
}
/// <summary>
- /// returns the value associated with the current key
+ /// Gets the current text as a newly created <see cref="string"/> object.
/// </summary>
- public virtual TValue CurrentValue
+ public string CurrentKeyString
{
get
{
- var val = outerInstance.values[lastPos];
- return val != null ? val.Value : default;
+ if (notStartedOrEnded)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+
+ char[] key = dictionary.keys[lastPos];
+ if (key is null)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ return new string(key);
}
}
/// <summary>
- /// sets the value associated with the last key returned
+ /// Gets the value associated with the current text.
/// </summary>
- public virtual TValue SetValue(TValue value)
+ [MaybeNull]
+ public TValue CurrentValue
{
- if (!allowModify)
+ get
{
- throw UnsupportedOperationException.Create();
+ if (notStartedOrEnded)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+ char[] key = dictionary.keys[lastPos];
+ if (key is null)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+
+ var val = dictionary.values[lastPos];
+ return val != null ? val.Value : default;
}
- TValue old = outerInstance.values[lastPos].Value;
- outerInstance.values[lastPos].Value = value;
+ }
+
+ /// <summary>
+ /// Sets the value associated with the current text.
+ /// </summary>
+ /// <returns>Returns the value prior to the update.</returns>
+ [return: MaybeNull]
+ public TValue SetValue(TValue value)
+ {
+ if (notStartedOrEnded)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+ if (!allowModify)
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+
+ MapValue current = dictionary.values[lastPos];
+ if (current is null)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+
+ TValue? old = current.Value;
+ // LUCENENET specific - increment the versions of both this enumerator
+ // and the original collection so only this enumerator instance isn't broken.
+ dictionary.version++;
+ version++;
+ current.Value = value;
return old;
}
// LUCENENET: Next() and Remove() methods eliminated here
#region Added for better .NET support LUCENENET
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- protected virtual void Dispose(bool disposing)
+ /// <summary>
+ /// Releases all resources used by the <see cref="Enumerator"/>.
+ /// </summary>
+ public void Dispose()
{
// nothing to do
}
- public virtual bool MoveNext()
- {
- if (!HasNext) return false;
+ /// <summary>
+ /// Advances the enumerator to the next element of the <see cref="CharArrayDictionary{TValue}"/>.
+ /// </summary>
+ /// <returns><c>true</c> if the enumerator was successfully advanced to the next element;
+ /// <c>false</c> if the enumerator has passed the end of the collection.</returns>
+ /// <exception cref="InvalidOperationException">The collection was modified after the enumerator was created.</exception>
+ /// <remarks>
+ /// After an enumerator is created, the enumerator is positioned before the first element in the collection,
+ /// and the first call to the <see cref="MoveNext()"/> method advances the enumerator to the first element
+ /// of the collection.
+ /// <para/>
+ /// If <see cref="MoveNext()"/> passes the end of the collection, the enumerator is positioned after the last element in the
+ /// collection and <see cref="MoveNext()"/> returns <c>false</c>. When the enumerator is at this position,
+ /// subsequent calls to <see cref="MoveNext()"/> also return <c>false</c>.
+ /// <para/>
+ /// An enumerator remains valid as long as the collection remains unchanged. If changes are made to the
+ /// collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated
+ /// and the next call to <see cref="MoveNext()"/> or <see cref="IEnumerator.Reset()"/> throws an
+ /// <see cref="InvalidOperationException"/>.
+ /// </remarks>
+ public bool MoveNext()
+ {
+ if (version != dictionary.version)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+
+ if (!HasNext)
+ {
+ notStartedOrEnded = true;
+ return false;
+ }
+ notStartedOrEnded = false;
GoNext();
return true;
}
- public virtual void Reset()
+ private void Reset()
{
+ if (version != dictionary.version)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+
pos = -1;
+ notStartedOrEnded = true;
GoNext();
}
- public virtual KeyValuePair<string, TValue> Current
+ void IEnumerator.Reset() => Reset();
+
+ void ICharArrayDictionaryEnumerator.Reset() => Reset();
+
+ /// <summary>
+ /// Gets the element at the current position of the enumerator.
+ /// </summary>
+ /// <remarks>
+ /// <see cref="Current"/> is undefined under any of the following conditions:
+ /// <list type="bullet">
+ /// <item><description>
+ /// The enumerator is positioned before the first element of the collection. That happens after an
+ /// enumerator is created or after the <see cref="IEnumerator.Reset()"/> method is called. The <see cref="MoveNext()"/>
+ /// method must be called to advance the enumerator to the first element of the collection before reading the value of
+ /// the <see cref="Current"/> property.
+ /// </description></item>
+ /// <item><description>
+ /// The last call to <see cref="MoveNext()"/> returned <c>false</c>, which indicates the end of the collection and that the
+ /// enumerator is positioned after the last element of the collection.
+ /// </description></item>
+ /// <item><description>
+ /// The enumerator is invalidated due to changes made in the collection, such as adding, modifying, or deleting elements.
+ /// </description></item>
+ /// </list>
+ /// <para/>
+ /// <see cref="Current"/> does not move the position of the enumerator, and consecutive calls to <see cref="Current"/> return
+ /// the same object until either <see cref="MoveNext()"/> or <see cref="IEnumerator.Reset()"/> is called.
+ /// </remarks>
+ public KeyValuePair<string, TValue> Current
{
get
{
- var val = outerInstance.values[lastPos];
- return new KeyValuePair<string, TValue>(
- new string(outerInstance.keys[lastPos]),
- val != null ? val.Value : default);
+ if (notStartedOrEnded)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+
+ char[] key = dictionary.keys[lastPos];
+ if (key is null)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ MapValue value = dictionary.values[lastPos];
+ return new KeyValuePair<string, TValue>(new string(key), value.Value!);
}
}
- object IEnumerator.Current => Current;
-
- #endregion
- }
-
- // LUCENENET NOTE: The Java Lucene type MapEntry was removed here because it is not possible
- // to inherit the value type KeyValuePair{TKey, TValue} in .NET.
-
- /// <summary>
- /// public EntrySet_ class so efficient methods are exposed to users
- ///
- /// NOTE: In .NET this was renamed to EntrySet_ because it conflicted with the
- /// method EntrySet(). Since there is also an extension method named <see cref="T:IDictionary{K,V}.EntrySet()"/>
- /// that this class needs to override, changing the name of the method was not
- /// possible because the extension method would produce incorrect results if it were
- /// inadvertently called, leading to hard-to-diagnose bugs.
- ///
- /// Another difference between this set and the Java counterpart is that it implements
- /// <see cref="ICollection{T}"/> rather than <see cref="ISet{T}"/> so we don't have to implement
- /// a bunch of methods that we aren't really interested in. The <see cref="Keys"/> and <see cref="Values"/>
- /// properties both return <see cref="ICollection{T}"/>, and while there is no <see cref="EntrySet()"/> method
- /// or property in .NET, if there were it would certainly return <see cref="ICollection{T}"/>.
- /// </summary>
- public sealed class EntrySet_ : ICollection<KeyValuePair<string, TValue>>
- {
- private readonly CharArrayMap<TValue> outerInstance;
-
- internal readonly bool allowModify;
-
- internal EntrySet_(CharArrayMap<TValue> outerInstance, bool allowModify)
+ object IEnumerator.Current
{
- this.outerInstance = outerInstance;
- this.allowModify = allowModify;
- }
+ get
+ {
+ if (notStartedOrEnded)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
- public IEnumerator GetEnumerator()
- {
- return new EntryIterator(outerInstance, allowModify);
- }
+ char[] key = dictionary.keys[lastPos];
+ if (key is null)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ MapValue value = dictionary.values[lastPos];
- IEnumerator<KeyValuePair<string, TValue>> IEnumerable<KeyValuePair<string, TValue>>.GetEnumerator()
- {
- return (IEnumerator<KeyValuePair<string, TValue>>)GetEnumerator();
+ if (getEnumeratorRetType == DictEntry)
+ {
+ return new DictionaryEntry(new string(key), value.Value);
+ }
+ else
+ {
+ return new KeyValuePair<string, TValue>(new string(key), value.Value!);
+ }
+ }
}
- public bool Contains(object o)
+ object IDictionaryEnumerator.Key
{
- if (!(o is KeyValuePair<string, TValue>))
+ get
{
- return false;
- }
- var e = (KeyValuePair<string, TValue>)o;
- string key = e.Key;
- TValue val = e.Value;
- TValue v = outerInstance.Get(key);
- return v is null ? val is null : v.Equals(val);
- }
+ if (notStartedOrEnded)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
- [Obsolete("Not applicable in this class.")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
- public bool Remove(KeyValuePair<string, TValue> item) // LUCENENET TODO: API - make an explicit implementation that isn't public
- {
- throw UnsupportedOperationException.Create();
+ return Current.Key;
+ }
}
- public int Count => outerInstance.count;
-
- public void Clear()
+ object? IDictionaryEnumerator.Value
{
- if (!allowModify)
+ get
{
- throw UnsupportedOperationException.Create();
+ if (notStartedOrEnded)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+
+ return Current.Value;
}
- outerInstance.Clear();
}
- #region LUCENENET Added for better .NET support
-
- public void CopyTo(KeyValuePair<string, TValue>[] array, int arrayIndex)
+ DictionaryEntry IDictionaryEnumerator.Entry
{
- outerInstance.CopyTo(array, arrayIndex);
- }
+ get
+ {
+ if (notStartedOrEnded)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
- [Obsolete("Not applicable in this class.")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
- public bool Contains(KeyValuePair<string, TValue> item)
- {
- return outerInstance.Contains(item);
+ return new DictionaryEntry(Current.Key, Current.Value);
+ }
}
- public void Add(KeyValuePair<string, TValue> item)
- {
- outerInstance.Add(item);
- }
+ bool ICharArrayDictionaryEnumerator.NotStartedOrEnded => notStartedOrEnded;
- public bool IsReadOnly => !allowModify;
+ #endregion
+ }
- public override string ToString()
- {
- var sb = new StringBuilder("[");
+ #endregion Nested Class: Enumerator
- IEnumerator<KeyValuePair<string, TValue>> iter1 = new EntryIterator(this.outerInstance, false);
- while (iter1.MoveNext())
- {
- KeyValuePair<string, TValue> entry = iter1.Current;
- if (sb.Length > 1)
- {
- sb.Append(", ");
- }
- sb.Append(entry.Key);
- sb.Append('=');
- sb.Append(entry.Value);
- }
+ // LUCENENET NOTE: The Java Lucene type MapEntry was removed here because it is not possible
+ // to inherit the value type KeyValuePair{TKey, TValue} in .NET.
- return sb.Append(']').ToString();
- }
- #endregion
- }
+ // LUCENENET: EntrySet class removed because in .NET we get the entries by calling GetEnumerator() on the dictionary.
- // LUCENENET: Moved UnmodifiableMap static methods to CharArrayMap class
+ // LUCENENET: Moved UnmodifiableMap static methods to CharArrayDictionary class
- // LUCENENET: Moved Copy static methods to CharArrayMap class
+ // LUCENENET: Moved Copy static methods to CharArrayDictionary class
- /// <summary>
- /// Returns an empty, unmodifiable map. </summary>
- public static CharArrayMap<TValue> EmptyMap()
- {
- return EMPTY_MAP;
- }
+ // LUCENENET: Removed EmptyMap() - use Empty instead
- // LUCENENET: Moved UnmodifiableCharArraymap to CharArrayMap class
+ // LUCENENET: Moved UnmodifiableCharArraymap to CharArrayDictionary class
- // LUCENENET: Moved EmptyCharArrayMap to CharArrayMap class
+ // LUCENENET: Moved EmptyCharArrayDictionary to CharArrayDictionary class
}
/// <summary>
/// LUCENENET specific interface used so <see cref="CharArraySet"/>
- /// can hold a reference to <see cref="CharArrayMap{TValue}"/> without
- /// knowing its generic type.
+ /// can hold a reference to <see cref="CharArrayDictionary{TValue}"/> without
+ /// knowing its generic closing type for TValue.
/// </summary>
- internal interface ICharArrayMap
+ internal interface ICharArrayDictionary
{
void Clear();
- bool ContainsKey(char[] text, int offset, int length);
+ bool ContainsKey(char[] text, int startIndex, int length);
bool ContainsKey(char[] text);
- bool ContainsKey(object o);
+ bool ContainsKey<T>(T text);
bool ContainsKey(string text);
bool ContainsKey(ICharSequence text);
int Count { get; }
+ bool IgnoreCase { get; }
+ bool IsReadOnly { get; }
LuceneVersion MatchVersion { get; }
- ICollection<string> OriginalKeySet { get; }
+ bool Put(char[] text, int startIndex, int Length);
bool Put(char[] text);
bool Put(ICharSequence text);
- bool Put(object o);
+ bool Put<T>(T text);
bool Put(string text);
+ void Set(char[] text, int startIndex, int length);
+ void Set(char[] text);
+ void Set(ICharSequence text);
+ void Set<T>(T text);
+ void Set(string text);
+ ICharArrayDictionaryEnumerator GetEnumerator();
}
- public static class CharArrayMap // LUCENENET specific: CA1052 Static holder types should be Static or NotInheritable
+ /// <summary>
+ /// LUCENENET specific interface used so <see cref="CharArraySet"/> can
+ /// iterate the keys of <see cref="CharArrayDictionary{TValue}"/> without
+ /// knowing its generic closing type for TValue.
+ /// </summary>
+ internal interface ICharArrayDictionaryEnumerator : IDisposable
+ {
+ bool NotStartedOrEnded { get; }
+ bool MoveNext();
+ ICharSequence CurrentKeyCharSequence { get; }
+ string CurrentKeyString { get; }
+ char[] CurrentKey { get; }
+ void Reset();
+ }
+
+ public static class CharArrayDictionary // LUCENENET specific: CA1052 Static holder types should be Static or NotInheritable
{
/// <summary>
- /// Returns a copy of the given map as a <see cref="CharArrayMap{TValue}"/>. If the given map
- /// is a <see cref="CharArrayMap{TValue}"/> the ignoreCase property will be preserved.
+ /// Returns a copy of the given dictionary as a <see cref="CharArrayDictionary{TValue}"/>. If the given dictionary
+ /// is a <see cref="CharArrayDictionary{TValue}"/> the ignoreCase property will be preserved.
/// <para>
- /// <b>Note:</b> If you intend to create a copy of another <see cref="CharArrayMap{TValue}"/> where
- /// the <see cref="LuceneVersion"/> of the source map differs from its copy
- /// <see cref="CharArrayMap{TValue}.CharArrayMap(LuceneVersion, IDictionary{string, TValue}, bool)"/> should be used instead.
+ /// <b>Note:</b> If you intend to create a copy of another <see cref="CharArrayDictionary{TValue}"/> where
+ /// the <see cref="LuceneVersion"/> of the source dictionary differs from its copy
+ /// <see cref="CharArrayDictionary{TValue}.CharArrayDictionary(LuceneVersion, IDictionary{string, TValue}, bool)"/> should be used instead.
/// The <see cref="Copy{TValue}(LuceneVersion, IDictionary{string, TValue})"/> will preserve the <see cref="LuceneVersion"/> of the
- /// source map if it is an instance of <see cref="CharArrayMap{TValue}"/>.
+ /// source dictionary if it is an instance of <see cref="CharArrayDictionary{TValue}"/>.
/// </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 <see cref="CharArrayMap{TValue}"/>. </param>
- /// <param name="map">
- /// a map to copy </param>
- /// <returns> a copy of the given map as a <see cref="CharArrayMap{TValue}"/>. If the given map
- /// is a <see cref="CharArrayMap{TValue}"/> the ignoreCase property as well as the
- /// <paramref name="matchVersion"/> will be of the given map will be preserved. </returns>
- public static CharArrayMap<TValue> Copy<TValue>(LuceneVersion matchVersion, IDictionary<string, TValue> map)
+ /// given dictionary is a <see cref="CharArrayDictionary{TValue}"/>. </param>
+ /// <param name="dictionary">
+ /// a dictionary to copy </param>
+ /// <returns> a copy of the given dictionary as a <see cref="CharArrayDictionary{TValue}"/>. If the given dictionary
+ /// is a <see cref="CharArrayDictionary{TValue}"/> the ignoreCase property as well as the
+ /// <paramref name="matchVersion"/> will be of the given dictionary will be preserved. </returns>
+ public static CharArrayDictionary<TValue> Copy<TValue>(LuceneVersion matchVersion, IDictionary<string, TValue> dictionary)
{
- if (map == CharArrayMap<TValue>.EmptyMap())
+ if (dictionary == CharArrayDictionary<TValue>.Empty)
{
- return CharArrayMap<TValue>.EmptyMap();
+ return CharArrayDictionary<TValue>.Empty;
}
- if (map is CharArrayMap<TValue>)
+ if (dictionary is CharArrayDictionary<TValue> m)
{
- var m = map as CharArrayMap<TValue>;
// 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 CharArrayMap<TValue>.MapValue[m.values.Length];
- Array.Copy(m.values, 0, values, 0, values.Length);
- m = new CharArrayMap<TValue>(m) { keys = keys, values = values };
+ m.keys.AsSpan().CopyTo(keys.AsSpan());
+ var values = new CharArrayDictionary<TValue>.MapValue[m.values.Length];
+ m.values.AsSpan().CopyTo(values.AsSpan());
+ m = new CharArrayDictionary<TValue>(m) { keys = keys, values = values };
return m;
}
- return new CharArrayMap<TValue>(matchVersion, map, false);
+ return new CharArrayDictionary<TValue>(matchVersion, dictionary, false);
}
/// <summary>
- /// Used by <see cref="CharArraySet"/> to copy <see cref="CharArrayMap{TValue}"/> without knowing
+ /// Used by <see cref="CharArraySet"/> to copy <see cref="CharArrayDictionary{TValue}"/> without knowing
/// its generic type.
/// </summary>
- internal static CharArrayMap<TValue> Copy<TValue>(LuceneVersion matchVersion, ICharArrayMap map)
+ internal static CharArrayDictionary<TValue> Copy<TValue>(LuceneVersion matchVersion, [DisallowNull] ICharArrayDictionary map)
{
- return Copy(matchVersion, map as IDictionary<string, TValue>);
+ return Copy(matchVersion, (IDictionary<string, TValue>)map);
}
/// <summary>
- /// Returns an unmodifiable <see cref="CharArrayMap{TValue}"/>. This allows to provide
- /// unmodifiable views of internal map for "read-only" use.
+ /// Returns an unmodifiable <see cref="CharArrayDictionary{TValue}"/>. This allows to provide
+ /// unmodifiable views of internal dictionary for "read-only" use.
/// </summary>
/// <param name="map">
- /// a map for which the unmodifiable map is returned. </param>
- /// <returns> an new unmodifiable <see cref="CharArrayMap{TValue}"/>. </returns>
+ /// a dictionary for which the unmodifiable dictionary is returned. </param>
+ /// <returns> an new unmodifiable <see cref="CharArrayDictionary{TValue}"/>. </returns>
/// <exception cref="ArgumentException">
- /// if the given map is <c>null</c>. </exception>
- [Obsolete("Use the CharArrayMap<TValue>.AsReadOnly() instance method instead. This method will be removed in 4.8.0 release candidate."), EditorBrowsable(EditorBrowsableState.Never)]
- public static CharArrayMap<TValue> UnmodifiableMap<TValue>(CharArrayMap<TValue> map)
+ /// if the given dictionary is <c>null</c>. </exception>
+ [Obsolete("Use the CharArrayDictionary<TValue>.AsReadOnly() instance method instead. This method will be removed in 4.8.0 release candidate."), EditorBrowsable(EditorBrowsableState.Never)]
+ public static CharArrayDictionary<TValue> UnmodifiableMap<TValue>(CharArrayDictionary<TValue> map)
{
if (map is null)
{
- throw new ArgumentNullException(nameof(map), "Given map is null"); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
+ throw new ArgumentNullException(nameof(map)); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
}
- if (map == CharArrayMap<TValue>.EmptyMap() || map.Count == 0)
+ if (map == CharArrayDictionary<TValue>.Empty || map.Count == 0)
{
- return CharArrayMap<TValue>.EmptyMap();
+ return CharArrayDictionary<TValue>.Empty;
}
- if (map is CharArrayMap.UnmodifiableCharArrayMap<TValue>)
+ if (map is CharArrayDictionary.ReadOnlyCharArrayDictionary<TValue>)
{
return map;
}
- return new CharArrayMap.UnmodifiableCharArrayMap<TValue>(map);
+ return new CharArrayDictionary.ReadOnlyCharArrayDictionary<TValue>(map);
}
/// <summary>
- /// Used by <see cref="CharArraySet"/> to create an <see cref="UnmodifiableCharArrayMap{TValue}"/> instance
+ /// Used by <see cref="CharArraySet"/> to create an <see cref="ReadOnlyCharArrayDictionary{TValue}"/> instance
/// without knowing the type of <typeparamref name="TValue"/>.
/// </summary>
- internal static ICharArrayMap UnmodifiableMap<TValue>(ICharArrayMap map)
+ internal static ICharArrayDictionary UnmodifiableMap<TValue>(ICharArrayDictionary map)
{
if (map is null)
{
- throw new ArgumentNullException(nameof(map), "Given map is null"); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
+ throw new ArgumentNullException(nameof(map)); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
}
- if (map == CharArrayMap<TValue>.EmptyMap() || map.Count == 0)
+ if (map == CharArrayDictionary<TValue>.Empty || map.Count == 0)
{
- return CharArrayMap<TValue>.EmptyMap();
+ return CharArrayDictionary<TValue>.Empty;
}
- if (map is CharArrayMap.UnmodifiableCharArrayMap<TValue>)
+ if (map is CharArrayDictionary.ReadOnlyCharArrayDictionary<TValue>)
{
return map;
}
- return new CharArrayMap.UnmodifiableCharArrayMap<TValue>(map);
+ return new CharArrayDictionary.ReadOnlyCharArrayDictionary<TValue>(map);
}
+ #region Nested Class: ReadOnlyCharArrayDictionary<TValue>
+
// package private CharArraySet instanceof check in CharArraySet
- internal class UnmodifiableCharArrayMap<TValue> : CharArrayMap<TValue>
+ internal class ReadOnlyCharArrayDictionary<TValue> : CharArrayDictionary<TValue>
{
- public UnmodifiableCharArrayMap(CharArrayMap<TValue> map)
+ public ReadOnlyCharArrayDictionary([DisallowNull] CharArrayDictionary<TValue> map)
: base(map)
{ }
- public UnmodifiableCharArrayMap(ICharArrayMap map)
- : base(map as CharArrayMap<TValue>)
+ public ReadOnlyCharArrayDictionary([DisallowNull] ICharArrayDictionary map)
+ : base((CharArrayDictionary<TValue>)map)
{ }
public override void Clear()
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override TValue Put(char[] text, TValue val)
+ public override bool Put(char[] text, int startIndex, int length, TValue value, [MaybeNullWhen(true)] out TValue previousValue)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override TValue Put(ICharSequence text, TValue val)
+ public override bool Put(char[] text, TValue value, [MaybeNullWhen(true)] out TValue previousValue)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override TValue Put(string text, TValue val)
+ public override bool Put(ICharSequence text, TValue val, [MaybeNullWhen(true)] out TValue previousValue)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override TValue Put(object o, TValue val)
+ public override bool Put(string text, TValue val, [MaybeNullWhen(true)] out TValue previousValue)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override bool Put(char[] text)
+ public override bool Put<T>(T text, TValue val, [MaybeNullWhen(true)] out TValue previousValue)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override bool Put(ICharSequence text)
+ internal override bool Put(char[] text, int startIndex, int length)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override bool Put(string text)
+ internal override bool Put(char[] text)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override bool Put(object o)
+ internal override bool Put(ICharSequence text)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- [Obsolete("Not applicable in this class.")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
- public override bool Remove(string key)
+ internal override bool Put(string text)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- internal override EntrySet_ CreateEntrySet()
+ internal override bool Put<T>(T text)
{
- return new EntrySet_(this, false);
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
+ // LUCENENET: Removed CreateEntrySet() method - we use IsReadOnly to control whether it can be written to
+
#region Added for better .NET support LUCENENET
- public override void Add(string key, TValue value)
+
+ public override bool IsReadOnly => true;
+
+ public override void Add(string text, TValue value)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override void Add(KeyValuePair<string, TValue> item)
+
+ public override void Add(char[] text, TValue value)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override TValue this[char[] key, int offset, int length]
+
+ public override void Add(ICharSequence text, TValue value)
{
- get => base[key, offset, length];
- set => throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override TValue this[char[] key]
+
+ public override void Add<T>(T text, TValue value)
{
- get => base[key];
- set => throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override TValue this[ICharSequence key]
+
+ public override TValue this[char[] text, int startIndex, int length]
{
- get => base[key];
- set => throw UnsupportedOperationException.Create();
+ get => base[text, startIndex, length];
+ set => throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override TValue this[string key]
+
+ public override TValue this[char[] text]
{
- get => base[key];
- set => throw UnsupportedOperationException.Create();
+ get => base[text];
+ set => throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override TValue this[object key]
+
+ public override TValue this[ICharSequence text]
{
- get => base[key];
- set => throw UnsupportedOperationException.Create();
+ get => base[text];
+ set => throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- [Obsolete("Not applicable in this class.")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
- public override bool Remove(KeyValuePair<string, TValue> item)
+ public override TValue this[string text]
{
- throw UnsupportedOperationException.Create();
+ get => base[text];
+ set => throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- #endregion
- }
- /// <summary>
- /// Empty <see cref="UnmodifiableCharArrayMap{V}"/> optimized for speed.
- /// Contains checks will always return <c>false</c> or throw
- /// NPE if necessary.
- /// </summary>
- internal class EmptyCharArrayMap<V> : UnmodifiableCharArrayMap<V>
- {
- public EmptyCharArrayMap()
-#pragma warning disable 612, 618
- : base(new CharArrayMap<V>(LuceneVersion.LUCENE_CURRENT, 0, false))
-#pragma warning restore 612, 618
+ public override TValue this[object text]
{
+ get => base[text];
+ set => throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override bool ContainsKey(char[] text, int offset, int length)
+ public override void PutAll(IDictionary<string, TValue> collection)
{
- if (text is null)
- {
- throw new ArgumentNullException(nameof(text));
- }
- return false;
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override bool ContainsKey(char[] text)
+ public override void PutAll(IDictionary<char[], TValue> collection)
{
- if (text is null)
- {
- throw new ArgumentNullException(nameof(text));
- }
- return false;
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override bool ContainsKey(ICharSequence text)
+ public override void PutAll(IDictionary<ICharSequence, TValue> collection)
{
- if (text is null)
- {
- throw new ArgumentNullException(nameof(text));
- }
- return false;
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override bool ContainsKey(object o)
+ public override void PutAll<T>(IDictionary<T, TValue> collection)
{
- if (o is null)
- {
- throw new ArgumentNullException(nameof(o));
- }
- return false;
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override V Get(char[] text, int offset, int length)
+ public override void PutAll(IEnumerable<KeyValuePair<string, TValue>> collection)
{
- if (text is null)
- {
- throw new ArgumentNullException(nameof(text));
- }
- return default;
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override V Get(char[] text)
+ public override void PutAll(IEnumerable<KeyValuePair<char[], TValue>> collection)
{
- if (text is null)
- {
- throw new ArgumentNullException(nameof(text));
- }
- return default;
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override V Get(ICharSequence text)
+ public override void PutAll(IEnumerable<KeyValuePair<ICharSequence, TValue>> collection)
{
- if (text is null)
- {
- throw new ArgumentNullException(nameof(text));
- }
- return default;
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- public override V Get(object o)
+ public override void PutAll<T>(IEnumerable<KeyValuePair<T, TValue>> collection)
{
- if (o is null)
- {
- throw new ArgumentNullException(nameof(o));
- }
- return default;
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
- }
- }
-
- /// <summary>
- /// LUCENENET specific extension methods for CharArrayMap
- /// </summary>
- public static class CharArrayMapExtensions
- {
- #region ContainsKey
-
- /// <summary>
- /// <c>true</c> if the <paramref name="key"/> <see cref="bool"/> is in the <see cref="CharArrayMap{TValue}.KeySet"/>;
- /// otherwise <c>false</c>
- /// </summary>
- public static bool ContainsKey<TValue>(this CharArrayMap<TValue> map, bool key)
- {
- return map.ContainsKey(key.ToString());
- }
- /// <summary>
- /// <c>true</c> if the <paramref name="key"/> <see cref="byte"/> is in the <see cref="CharArrayMap{TValue}.KeySet"/>;
- /// otherwise <c>false</c>
- /// </summary>
- public static bool ContainsKey<TValue>(this CharArrayMap<TValue> map, byte key)
- {
- return map.ContainsKey(key.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// <c>true</c> if the <paramref name="key"/> <see cref="char"/> is in the <see cref="CharArrayMap{TValue}.KeySet"/>;
- /// otherwise <c>false</c>
- /// </summary>
- public static bool ContainsKey<TValue>(this CharArrayMap<TValue> map, char key)
- {
- return map.ContainsKey("" + key);
- }
+ internal override void Set(char[] text)
+ {
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+ }
- ///// <summary>
- ///// <c>true</c> if the <paramref name="key"/> <see cref="decimal"/> is in the <see cref="CharArrayMap{TValue}.KeySet"/>;
- ///// otherwise <c>false</c>
- ///// </summary>
- //public static bool ContainsKey<TValue>(this CharArrayMap<TValue> map, decimal key)
- //{
- // return map.ContainsKey(key.ToString(CultureInfo.InvariantCulture));
- //}
+ internal override void Set(char[] text, TValue? value)
+ {
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+ }
- ///// <summary>
- ///// <c>true</c> if the <paramref name="key"/> <see cref="double"/> is in the <see cref="CharArrayMap{TValue}.KeySet"/>;
- ///// otherwise <c>false</c>
- ///// </summary>
- //public static bool ContainsKey<TValue>(this CharArrayMap<TValue> map, double key)
- //{
- // return map.ContainsKey(key.ToString(CultureInfo.InvariantCulture));
- //}
+ internal override void Set(char[] text, int startIndex, int length)
+ {
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+ }
- ///// <summary>
- ///// <c>true</c> if the <paramref name="key"/> <see cref="float"/> is in the <see cref="CharArrayMap{TValue}.KeySet"/>;
- ///// otherwise <c>false</c>
- ///// </summary>
- //public static bool ContainsKey<TValue>(this CharArrayMap<TValue> map, float key)
- //{
- // return map.ContainsKey(key.ToString(CultureInfo.InvariantCulture));
- //}
+ internal override void Set(char[] text, int startIndex, int length, TValue? value)
+ {
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+ }
- /// <summary>
- /// <c>true</c> if the <paramref name="key"/> <see cref="int"/> is in the <see cref="CharArrayMap{TValue}.KeySet"/>;
- /// otherwise <c>false</c>
- /// </summary>
- public static bool ContainsKey<TValue>(this CharArrayMap<TValue> map, int key)
- {
- return map.ContainsKey(key.ToString(CultureInfo.InvariantCulture));
- }
+ internal override void Set(ICharSequence text)
+ {
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+ }
- /// <summary>
- /// <c>true</c> if the <paramref name="key"/> <see cref="long"/> is in the <see cref="CharArrayMap{TValue}.KeySet"/>;
- /// otherwise <c>false</c>
- /// </summary>
- public static bool ContainsKey<TValue>(this CharArrayMap<TValue> map, long key)
- {
- return map.ContainsKey(key.ToString(CultureInfo.InvariantCulture));
- }
+ internal override void Set(ICharSequence text, TValue? value)
+ {
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+ }
- /// <summary>
- /// <c>true</c> if the <paramref name="key"/> <see cref="sbyte"/> is in the <see cref="CharArrayMap{TValue}.KeySet"/>;
- /// otherwise <c>false</c>
- /// </summary>
- [CLSCompliant(false)]
- public static bool ContainsKey<TValue>(this CharArrayMap<TValue> map, sbyte key)
- {
- return map.ContainsKey(key.ToString(CultureInfo.InvariantCulture));
- }
+ internal override void Set(string text)
+ {
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+ }
- /// <summary>
- /// <c>true</c> if the <paramref name="key"/> <see cref="short"/> is in the <see cref="CharArrayMap{TValue}.KeySet"/>;
- /// otherwise <c>false</c>
- /// </summary>
- public static bool ContainsKey<TValue>(this CharArrayMap<TValue> map, short key)
- {
- return map.ContainsKey(key.ToString(CultureInfo.InvariantCulture));
- }
+ internal override void Set(string text, TValue? value)
+ {
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+ }
- /// <summary>
- /// <c>true</c> if the <paramref name="key"/> <see cref="uint"/> is in the <see cref="CharArrayMap{TValue}.KeySet"/>;
- /// otherwise <c>false</c>
- /// </summary>
- [CLSCompliant(false)]
- public static bool ContainsKey<TValue>(this CharArrayMap<TValue> map, uint key)
- {
- return map.ContainsKey(key.ToString(CultureInfo.InvariantCulture));
- }
+ internal override void Set<T>(T text)
+ {
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+ }
- /// <summary>
- /// <c>true</c> if the <paramref name="key"/> <see cref="ulong"/> is in the <see cref="CharArrayMap{TValue}.KeySet"/>;
- /// otherwise <c>false</c>
- /// </summary>
- [CLSCompliant(false)]
- public static bool ContainsKey<TValue>(this CharArrayMap<TValue> map, ulong key)
- {
- return map.ContainsKey(key.ToString(CultureInfo.InvariantCulture));
- }
+ internal override void Set<T>(T text, TValue? value)
+ {
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+ }
- /// <summary>
- /// <c>true</c> if the <paramref name="key"/> <see cref="ushort"/> is in the <see cref="CharArrayMap{TValue}.KeySet"/>;
- /// otherwise <c>false</c>
- /// </summary>
- [CLSCompliant(false)]
- public static bool ContainsKey<TValue>(this CharArrayMap<TValue> map, ushort key)
- {
- return map.ContainsKey(key.ToString(CultureInfo.InvariantCulture));
+ #endregion
}
#endregion
- #region Get
-
- /// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
- /// </summary>
- public static TValue Get<TValue>(this CharArrayMap<TValue> map, bool text)
- {
- return map.Get(text.ToString());
- }
-
- /// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
- /// </summary>
- public static TValue Get<TValue>(this CharArrayMap<TValue> map, byte text)
- {
- return map.Get(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
- /// </summary>
- public static TValue Get<TValue>(this CharArrayMap<TValue> map, char text)
- {
- return map.Get("" + text);
- }
-
- /// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
- /// </summary>
- public static TValue Get<TValue>(this CharArrayMap<TValue> map, decimal text)
- {
- return map.Get(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
- /// </summary>
- public static TValue Get<TValue>(this CharArrayMap<TValue> map, double text)
- {
- return map.Get(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
- /// </summary>
- public static TValue Get<TValue>(this CharArrayMap<TValue> map, float text)
- {
- return map.Get(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
- /// </summary>
- public static TValue Get<TValue>(this CharArrayMap<TValue> map, int text)
- {
- return map.Get(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
- /// </summary>
- public static TValue Get<TValue>(this CharArrayMap<TValue> map, long text)
- {
- return map.Get(text.ToString(CultureInfo.InvariantCulture));
- }
+ #region Nested Class: EmptyCharArrayDictionary<V>
/// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
- /// </summary>
- [CLSCompliant(false)]
- public static TValue Get<TValue>(this CharArrayMap<TValue> map, sbyte text)
- {
- return map.Get(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
- /// </summary>
- public static TValue Get<TValue>(this CharArrayMap<TValue> map, short text)
- {
- return map.Get(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
- /// </summary>
- [CLSCompliant(false)]
- public static TValue Get<TValue>(this CharArrayMap<TValue> map, uint text)
- {
- return map.Get(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
+ /// Empty <see cref="ReadOnlyCharArrayDictionary{V}"/> optimized for speed.
+ /// Contains checks will always return <c>false</c> or throw
+ /// NPE if necessary.
/// </summary>
- [CLSCompliant(false)]
- public static TValue Get<TValue>(this CharArrayMap<TValue> map, ulong text)
+ internal class EmptyCharArrayDictionary<V> : ReadOnlyCharArrayDictionary<V>
{
- return map.Get(text.ToString(CultureInfo.InvariantCulture));
- }
+ public EmptyCharArrayDictionary()
+#pragma warning disable 612, 618
+ : base(new CharArrayDictionary<V>(LuceneVersion.LUCENE_CURRENT, 0, false))
+#pragma warning restore 612, 618
+ {
+ }
- /// <summary>
- /// returns the value of the mapping of the chars inside this <paramref name="text"/>
- /// </summary>
- [CLSCompliant(false)]
- public static TValue Get<TValue>(this CharArrayMap<TValue> map, ushort text)
- {
- return map.Get(text.ToString(CultureInfo.InvariantCulture));
- }
+ public override bool ContainsKey(char[] text, int startIndex, int length)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
- #endregion
+ return false;
+ }
- #region Put
+ public override bool ContainsKey(char[] text)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
- /// <summary>
- /// Add the given mapping.
- /// </summary>
- public static TValue Put<TValue>(this CharArrayMap<TValue> map, bool text, TValue value)
- {
- return map.Put(text.ToString(), value);
- }
+ return false;
+ }
- /// <summary>
- /// Add the given mapping.
- /// </summary>
- public static TValue Put<TValue>(this CharArrayMap<TValue> map, byte text, TValue value)
- {
- return map.Put(text.ToString(), value);
- }
+ public override bool ContainsKey(ICharSequence text)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
- /// <summary>
- /// Add the given mapping.
- /// </summary>
- public static TValue Put<TValue>(this CharArrayMap<TValue> map, char text, TValue value)
- {
- return map.Put(text.ToString(), value);
- }
+ return false;
+ }
- ///// <summary>
- ///// Add the given mapping.
- ///// </summary>
- //public static TValue Put<TValue>(this CharArrayMap<TValue> map, decimal text, TValue value)
- //{
- // return map.Put(text.ToString(CultureInfo.InvariantCulture), value);
- //}
+ public override bool ContainsKey<T>(T text)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
- ///// <summary>
- ///// Add the given mapping.
- ///// </summary>
- //public static TValue Put<TValue>(this CharArrayMap<TValue> map, double text, TValue value)
- //{
- // return map.Put(text.ToString(CultureInfo.InvariantCulture), value);
- //}
+ return false;
+ }
- ///// <summary>
- ///// Add the given mapping.
- ///// </summary>
- //public static TValue Put<TValue>(this CharArrayMap<TValue> map, float text, TValue value)
- //{
- // return map.Put(text.ToString(CultureInfo.InvariantCulture), value);
- //}
+ internal override V Get(char[] text, int startIndex, int length, bool throwIfNotfound = true)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
- /// <summary>
- /// Add the given mapping.
- /// </summary>
- public static TValue Put<TValue>(this CharArrayMap<TValue> map, int text, TValue value)
- {
- return map.Put(text.ToString(CultureInfo.InvariantCulture), value);
- }
+ if (throwIfNotfound)
+ throw new KeyNotFoundException(string.Format(SR.Arg_KeyNotFoundWithKey, new string(text, startIndex, length)));
+ return default!;
+ }
- /// <summary>
- /// Add the given mapping.
- /// </summary>
- public static TValue Put<TValue>(this CharArrayMap<TValue> map, long text, TValue value)
- {
- return map.Put(text.ToString(CultureInfo.InvariantCulture), value);
- }
+ internal override V Get(char[] text, bool throwIfNotfound = true)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
- /// <summary>
- /// Add the given mapping.
- /// </summary>
- [CLSCompliant(false)]
- public static TValue Put<TValue>(this CharArrayMap<TValue> map, sbyte text, TValue value)
- {
- return map.Put(text.ToString(CultureInfo.InvariantCulture), value);
- }
+ if (throwIfNotfound)
+ throw new KeyNotFoundException(string.Format(SR.Arg_KeyNotFoundWithKey, new string(text)));
+ return default!;
+ }
- /// <summary>
- /// Add the given mapping.
- /// </summary>
- public static TValue Put<TValue>(this CharArrayMap<TValue> map, short text, TValue value)
- {
- return map.Put(text.ToString(CultureInfo.InvariantCulture), value);
- }
+ internal override V Get(ICharSequence text, bool throwIfNotfound = true)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
- /// <summary>
- /// Add the given mapping.
- /// </summary>
- [CLSCompliant(false)]
- public static TValue Put<TValue>(this CharArrayMap<TValue> map, uint text, TValue value)
- {
- return map.Put(text.ToString(CultureInfo.InvariantCulture), value);
- }
+ if (throwIfNotfound)
+ throw new KeyNotFoundException(string.Format(SR.Arg_KeyNotFoundWithKey, text));
+ return default!;
+ }
- /// <summary>
- /// Add the given mapping.
- /// </summary>
- [CLSCompliant(false)]
- public static TValue Put<TValue>(this CharArrayMap<TValue> map, ulong text, TValue value)
- {
- return map.Put(text.ToString(CultureInfo.InvariantCulture), value);
- }
+ internal override V Get<T>(T text, bool throwIfNotfound = true)
+ {
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
- /// <summary>
- /// Add the given mapping.
- /// </summary>
- [CLSCompliant(false)]
- public static TValue Put<TValue>(this CharArrayMap<TValue> map, ushort text, TValue value)
- {
- return map.Put(text.ToString(CultureInfo.InvariantCulture), value);
+ if (throwIfNotfound)
+ throw new KeyNotFoundException(string.Format(SR.Arg_KeyNotFoundWithKey, text));
+ return default!;
+ }
}
#endregion
- #region PutAll
+ private readonly static CultureInfo invariant = CultureInfo.InvariantCulture;
+ private const string TrueString = "true";
+ private const string FalseString = "false";
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="dictionary"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="dictionary">A dictionary of values to add/update in the current map.</param>
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IDictionary<bool, TValue> dictionary)
- {
- foreach (var kvp in dictionary)
- {
- map.Put(kvp.Key.ToString(), kvp.Value);
- }
- }
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="dictionary"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="dictionary">A dictionary of values to add/update in the current map.</param>
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IDictionary<byte, TValue> dictionary)
+ internal enum CharReturnType
{
- foreach (var kvp in dictionary)
- {
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
- }
+ String = 0,
+ CharArray = 1,
}
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="dictionary"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="dictionary">A dictionary of values to add/update in the current map.</param>
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IDictionary<char, TValue> dictionary)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static CharReturnType ConvertObjectToChars<T>(T key, out char[] chars, out string str)
{
- foreach (var kvp in dictionary)
- {
- map.Put("" + kvp.Key, kvp.Value);
- }
+#if FEATURE_SPANFORMATTABLE
+ Span<char> buffer = stackalloc char[256];
+#else
+ Span<char> buffer = stackalloc char[1];
+#endif
+ return ConvertObjectToChars(key, out chars, out str, buffer);
}
- ///// <summary>
- ///// This implementation enumerates over the specified <paramref name="dictionary"/>'s
- ///// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- ///// </summary>
- ///// <param name="map">this map</param>
- ///// <param name="dictionary">A dictionary of values to add/update in the current map.</param>
- //public static void PutAll<TValue>(this CharArrayMap<TValue> map, IDictionary<decimal, TValue> dictionary)
- //{
- // foreach (var kvp in dictionary)
- // {
- // map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
- // }
- //}
- ///// <summary>
- ///// This implementation enumerates over the specified <paramref name="dictionary"/>'s
- ///// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- ///// </summary>
- ///// <param name="map">this map</param>
- ///// <param name="dictionary">A dictionary of values to add/update in the current map.</param>
- //public static void PutAll<TValue>(this CharArrayMap<TValue> map, IDictionary<double, TValue> dictionary)
- //{
- // foreach (var kvp in dictionary)
- // {
- // map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
- // }
- //}
-
- ///// <summary>
- ///// This implementation enumerates over the specified <paramref name="dictionary"/>'s
- ///// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- ///// </summary>
- ///// <param name="map">this map</param>
- ///// <param name="dictionary">A dictionary of values to add/update in the current map.</param>
- //public static void PutAll<TValue>(this CharArrayMap<TValue> map, IDictionary<float, TValue> dictionary)
- //{
- // foreach (var kvp in dictionary)
- // {
- // map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
- // }
- //}
-
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="dictionary"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="dictionary">A dictionary of values to add/update in the current map.</param>
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IDictionary<int, TValue> dictionary)
+ // LUCENENET: We need value types to be represented using the invariant
+ // culture, so it is consistent regardless of the current culture.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static CharReturnType ConvertObjectToChars<T>(T key, out char[] chars, out string str, Span<char> reuse)
{
- foreach (var kvp in dictionary)
- {
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
- }
- }
+ chars = Arrays.Empty<char>();
+ str = string.Empty;
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="dictionary"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="dictionary">A dictionary of values to add/update in the current map.</param>
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IDictionary<long, TValue> dictionary)
- {
- foreach (var kvp in dictionary)
+ if (key is null)
{
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ return CharReturnType.CharArray;
}
- }
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="dictionary"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="dictionary">A dictionary of values to add/update in the current map.</param>
- [CLSCompliant(false)]
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IDictionary<sbyte, TValue> dictionary)
- {
- foreach (var kvp in dictionary)
+ // Handle special cases
+ if (key is string strResult)
{
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ str = strResult;
+ return CharReturnType.String;
}
- }
-
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="dictionary"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="dictionary">A dictionary of values to add/update in the current map.</param>
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IDictionary<short, TValue> dictionary)
- {
- foreach (var kvp in dictionary)
+ else if (key is char[] charArray)
{
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ chars = charArray;
+ return CharReturnType.CharArray;
}
- }
-
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="dictionary"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="dictionary">A dictionary of values to add/update in the current map.</param>
- [CLSCompliant(false)]
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IDictionary<uint, TValue> dictionary)
- {
- foreach (var kvp in dictionary)
+ else if (key is IList<char> charList)
{
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ char[] result = new char[charList.Count];
+ charList.CopyTo(result, arrayIndex: 0);
+ chars = result;
+ return CharReturnType.CharArray;
}
- }
-
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="dictionary"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="dictionary">A dictionary of values to add/update in the current map.</param>
- [CLSCompliant(false)]
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IDictionary<ulong, TValue> dictionary)
- {
- foreach (var kvp in dictionary)
+ else if (key is StringBuilder stringBuilder)
{
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ char[] result = new char[stringBuilder.Length];
+ stringBuilder.CopyTo(sourceIndex: 0, result, destinationIndex: 0, stringBuilder.Length);
+ chars = result;
+ return CharReturnType.CharArray;
}
- }
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="dictionary"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="dictionary">A dictionary of values to add/update in the current map.</param>
- [CLSCompliant(false)]
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IDictionary<ushort, TValue> dictionary)
- {
- foreach (var kvp in dictionary)
+ // ICharSequence types
+ else if (key is StringCharSequence strCs)
{
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ str = strCs.Value ?? string.Empty;
+ return CharReturnType.String;
}
- }
-
-
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="collection"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="collection">The values to add/update in the current map.</param>
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IEnumerable<KeyValuePair<bool, TValue>> collection)
- {
- foreach (var kvp in collection)
+ else if (key is CharArrayCharSequence charArrayCs)
{
- map.Put(kvp.Key.ToString(), kvp.Value);
+ chars = charArrayCs.Value ?? Arrays.Empty<char>();
+ return CharReturnType.CharArray;
}
- }
-
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="collection"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="collection">The values to add/update in the current map.</param>
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IEnumerable<KeyValuePair<byte, TValue>> collection)
- {
- foreach (var kvp in collection)
+ else if (key is StringBuilderCharSequence stringBuilderCs && stringBuilderCs.HasValue)
{
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ var sb = stringBuilderCs.Value!;
+ char[] result = new char[sb.Length];
+ sb.CopyTo(sourceIndex: 0, result, destinationIndex: 0, sb.Length);
+ chars = result;
+ return CharReturnType.CharArray;
}
- }
-
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="collection"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="collection">The values to add/update in the current map.</param>
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IEnumerable<KeyValuePair<char, TValue>> collection)
- {
- foreach (var kvp in collection)
+ else if (key is ICharSequence cs && cs.HasValue)
{
- map.Put("" + kvp.Key, kvp.Value);
- }
- }
-
- ///// <summary>
- ///// This implementation enumerates over the specified <paramref name="collection"/>'s
- ///// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- ///// </summary>
- ///// <param name="map">this map</param>
- ///// <param name="collection">The values to add/update in the current map.</param>
- //public static void PutAll<TValue>(this CharArrayMap<TValue> map, IEnumerable<KeyValuePair<decimal, TValue>> collection)
- //{
- // foreach (var kvp in collection)
- // {
- // map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
- // }
- //}
-
- ///// <summary>
- ///// This implementation enumerates over the specified <paramref name="collection"/>'s
- ///// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- ///// </summary>
- ///// <param name="map">this map</param>
- ///// <param name="collection">The values to add/update in the current map.</param>
- //public static void PutAll<TValue>(this CharArrayMap<TValue> map, IEnumerable<KeyValuePair<double, TValue>> collection)
- //{
- // foreach (var kvp in collection)
- // {
- // map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
- // }
- //}
-
- ///// <summary>
- ///// This implementation enumerates over the specified <paramref name="collection"/>'s
- ///// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- ///// </summary>
- ///// <param name="map">this map</param>
- ///// <param name="collection">The values to add/update in the current map.</param>
- //public static void PutAll<TValue>(this CharArrayMap<TValue> map, IEnumerable<KeyValuePair<float, TValue>> collection)
- //{
- // foreach (var kvp in collection)
- // {
- // map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
- // }
- //}
-
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="collection"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="collection">The values to add/update in the current map.</param>
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IEnumerable<KeyValuePair<int, TValue>> collection)
- {
- foreach (var kvp in collection)
- {
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ int length = cs.Length;
+ char[] result = new char[length];
+ for (int i = 0; i < length; i++)
+ {
+ result[i] = cs[i];
+ }
+ chars = result;
+ return CharReturnType.CharArray;
}
- }
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="collection"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="collection">The values to add/update in the current map.</param>
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IEnumerable<KeyValuePair<long, TValue>> collection)
- {
- foreach (var kvp in collection)
+ // These must be done prior to checking ISpanFormattable and IFormattable
+ else if (key is bool b)
{
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ str = b ? TrueString : FalseString;
+ return CharReturnType.String;
}
- }
-
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="collection"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="collection">The values to add/update in the current map.</param>
- [CLSCompliant(false)]
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IEnumerable<KeyValuePair<sbyte, TValue>> collection)
- {
- foreach (var kvp in collection)
+ else if (key is double d)
{
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ str = J2N.Numerics.Double.ToString(d, invariant);
+ return CharReturnType.String;
}
- }
-
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="collection"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="collection">The values to add/update in the current map.</param>
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IEnumerable<KeyValuePair<short, TValue>> collection)
- {
- foreach (var kvp in collection)
+ else if (key is float f)
{
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ str = J2N.Numerics.Single.ToString(f, invariant);
+ return CharReturnType.String;
}
- }
-
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="collection"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="collection">The values to add/update in the current map.</param>
- [CLSCompliant(false)]
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IEnumerable<KeyValuePair<uint, TValue>> collection)
- {
- foreach (var kvp in collection)
+ else if (key is J2N.Numerics.Number number)
{
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ str = number.ToString(invariant);
+ return CharReturnType.String;
}
- }
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="collection"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="collection">The values to add/update in the current map.</param>
- [CLSCompliant(false)]
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IEnumerable<KeyValuePair<ulong, TValue>> collection)
- {
- foreach (var kvp in collection)
+#if FEATURE_SPANFORMATTABLE
+ else if (key is ISpanFormattable spanFormattable &&
+ spanFormattable.TryFormat(reuse, out int charsWritten, string.Empty.AsSpan(), invariant))
{
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ chars = reuse.Slice(0, charsWritten).ToArray();
+ return CharReturnType.CharArray;
}
- }
-
- /// <summary>
- /// This implementation enumerates over the specified <paramref name="collection"/>'s
- /// entries, and calls this map's <see cref="CharArrayMap{TValue}.Put(string, TValue)"/> operation once for each entry.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="collection">The values to add/update in the current map.</param>
- [CLSCompliant(false)]
- public static void PutAll<TValue>(this CharArrayMap<TValue> map, IEnumerable<KeyValuePair<ushort, TValue>> collection)
- {
- foreach (var kvp in collection)
+#endif
+ else if (key is IFormattable formattable)
{
- map.Put(kvp.Key.ToString(CultureInfo.InvariantCulture), kvp.Value);
+ str = formattable.ToString(string.Empty, invariant);
+ return CharReturnType.String;
}
- }
-
- #endregion
-
- #region TryGetValue
- /// <summary>
- /// Gets the value associated with the specified key.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
- /// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- public static bool TryGetValue<TValue>(this CharArrayMap<TValue> map, bool key, out TValue value)
- {
- return map.TryGetValue(key.ToString(), out value);
+ using var context = new CultureContext(invariant);
+ str = key.ToString() ?? string.Empty;
+ return CharReturnType.String;
}
+ }
+ /// <summary>
+ /// Extensions to <see cref="IDictionary{TKey, TValue}"/> for <see cref="CharArrayDictionary{TValue}"/>.
+ /// </summary>
+ // LUCENENET specific - allow .NET-like syntax for copying CharArrayDictionary
+ public static class DictionaryExtensions
+ {
/// <summary>
- /// Gets the value associated with the specified key.
+ /// Returns a copy of the current <see cref="IDictionary{TKey, TValue}"/> as a <see cref="CharArrayDictionary{TValue}"/>
+ /// using the specified <paramref name="matchVersion"/> value.
/// </summary>
- /// <param name="map">this map</param>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
- /// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- public static bool TryGetValue<TValue>(this CharArrayMap<TValue> map, byte key, out TValue value)
+ /// <typeparam name="TValue">The type of dictionary value.</typeparam>
+ /// <param name="dictionary">
+ /// A <see cref="IDictionary{TKey, TValue}"/> to copy. </param>
+ /// <param name="matchVersion">
+ /// compatibility match version see <a href="#version">Version
+ /// note</a> above for details. </param>
+ /// <returns> A copy of the current dictionary as a <see cref="CharArrayDictionary{TValue}"/>. </returns>
+ /// <exception cref="ArgumentNullException"><paramref name="dictionary"/> is <c>null</c>.</exception>
+ public static CharArrayDictionary<TValue> ToCharArrayDictionary<TValue>(this IDictionary<string, TValue> dictionary, LuceneVersion matchVersion)
{
- return map.TryGetValue(key.ToString(CultureInfo.InvariantCulture), out value);
- }
+ if (dictionary is null)
+ throw new ArgumentNullException(nameof(dictionary));
- /// <summary>
- /// Gets the value associated with the specified key.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
- /// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- public static bool TryGetValue<TValue>(this CharArrayMap<TValue> map, char key, out TValue value)
- {
- return map.TryGetValue("" + key, out value);
- }
-
- ///// <summary>
- ///// Gets the value associated with the specified key.
- ///// </summary>
- ///// <param name="map">this map</param>
- ///// <param name="key">The key of the value to get.</param>
- ///// <param name="value">When this method returns, contains the value associated with the specified key,
- ///// if the key is found; otherwise, the default value for the type of the value parameter.
- ///// This parameter is passed uninitialized.</param>
- ///// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- //public static bool TryGetValue<TValue>(this CharArrayMap<TValue> map, decimal key, out TValue value)
- //{
- // return map.TryGetValue(key.ToString(CultureInfo.InvariantCulture), out value);
- //}
-
- ///// <summary>
- ///// Gets the value associated with the specified key.
- ///// </summary>
- ///// <param name="map">this map</param>
- ///// <param name="key">The key of the value to get.</param>
- ///// <param name="value">When this method returns, contains the value associated with the specified key,
- ///// if the key is found; otherwise, the default value for the type of the value parameter.
- ///// This parameter is passed uninitialized.</param>
- ///// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- //public static bool TryGetValue<TValue>(this CharArrayMap<TValue> map, double key, out TValue value)
- //{
- // return map.TryGetValue(key.ToString(CultureInfo.InvariantCulture), out value);
- //}
-
- ///// <summary>
- ///// Gets the value associated with the specified key.
- ///// </summary>
- ///// <param name="map">this map</param>
- ///// <param name="key">The key of the value to get.</param>
- ///// <param name="value">When this method returns, contains the value associated with the specified key,
- ///// if the key is found; otherwise, the default value for the type of the value parameter.
- ///// This parameter is passed uninitialized.</param>
- ///// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- //public static bool TryGetValue<TValue>(this CharArrayMap<TValue> map, float key, out TValue value)
- //{
- // return map.TryGetValue(key.ToString(CultureInfo.InvariantCulture), out value);
- //}
-
- /// <summary>
- /// Gets the value associated with the specified key.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
- /// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- public static bool TryGetValue<TValue>(this CharArrayMap<TValue> map, int key, out TValue value)
- {
- return map.TryGetValue(key.ToString(CultureInfo.InvariantCulture), out value);
+ return CharArrayDictionary.Copy<TValue>(matchVersion, dictionary);
}
/// <summary>
- /// Gets the value associated with the specified key.
+ /// Returns a copy of the current <see cref="IDictionary{TKey, TValue}"/> as a <see cref="CharArrayDictionary{TValue}"/>
+ /// using the specified <paramref name="matchVersion"/> and <paramref name="ignoreCase"/> values.
/// </summary>
- /// <param name="map">this map</param>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
- /// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- public static bool TryGetValue<TValue>(this CharArrayMap<TValue> map, long key, out TValue value)
+ /// <typeparam name="TValue">The type of dictionary value.</typeparam>
+ /// <param name="dictionary">
+ /// A <see cref="IDictionary{TKey, TValue}"/> to copy. </param>
+ /// <param name="matchVersion">
+ /// compatibility match version see <a href="#version">Version
+ /// note</a> above for details. </param>
+ /// <param name="ignoreCase"><c>false</c> if and only if the set should be case sensitive otherwise <c>true</c>.</param>
+ /// <returns> A copy of the current dictionary as a <see cref="CharArrayDictionary{TValue}"/>. </returns>
+ /// <exception cref="ArgumentNullException"><paramref name="dictionary"/> is <c>null</c>.</exception>
+ public static CharArrayDictionary<TValue> ToCharArrayDictionary<TValue>(this IDictionary<string, TValue> dictionary, LuceneVersion matchVersion, bool ignoreCase)
{
- return map.TryGetValue(key.ToString(CultureInfo.InvariantCulture), out value);
- }
+ if (dictionary is null)
+ throw new ArgumentNullException(nameof(dictionary));
- /// <summary>
- /// Gets the value associated with the specified key.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
- /// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- [CLSCompliant(false)]
- public static bool TryGetValue<TValue>(this CharArrayMap<TValue> map, sbyte key, out TValue value)
- {
- return map.TryGetValue(key.ToString(CultureInfo.InvariantCulture), out value);
+ return new CharArrayDictionary<TValue>(matchVersion, dictionary.Count, ignoreCase);
}
+ }
- /// <summary>
- /// Gets the value associated with the specified key.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
- /// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- public static bool TryGetValue<TValue>(this CharArrayMap<TValue> map, short key, out TValue value)
- {
- return map.TryGetValue(key.ToString(CultureInfo.InvariantCulture), out value);
- }
+ /// <summary>
+ /// LUCENENET specific. Just a class to make error messages easier to manage in one place.
+ /// Ideally, these would be in resources so they can be localized (eventually), but at least
+ /// this half-measure will make that somewhat easier to do and is guaranteed not to cause
+ /// performance issues.
+ /// </summary>
+ internal static class SR
+ {
+ public const string Arg_ArrayPlusOffTooSmall = "Destination array is not long enough to copy all the items in the collection. Check array index and length.";
+ public const string Arg_KeyNotFoundWithKey = "The given text '{0}' was not present in the dictionary.";
+ public const string Arg_NonZeroLowerBound = "The lower bound of target array must be zero.";
+ public const string Arg_RankMultiDimNotSupported = "Only single dimensional arrays are supported for the requested action.";
+ public const string Arg_WrongType = "The value '{0}' is not of type '{1}' and cannot be used in this generic collection.";
- /// <summary>
- /// Gets the value associated with the specified key.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
- /// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- [CLSCompliant(false)]
- public static bool TryGetValue<TValue>(this CharArrayMap<TValue> map, uint key, out TValue value)
- {
- return map.TryGetValue(key.ToString(CultureInfo.InvariantCulture), out value);
- }
+ public const string Argument_AddingDuplicate = "An item with the same text has already been added. Key: {0}";
+ public const string Argument_InvalidArrayType = "Target array type is not compatible with the type of items in the collection.";
- /// <summary>
- /// Gets the value associated with the specified key.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
- /// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- [CLSCompliant(false)]
- public static bool TryGetValue<TValue>(this CharArrayMap<TValue> map, ulong key, out TValue value)
- {
- return map.TryGetValue(key.ToString(CultureInfo.InvariantCulture), out value);
- }
+ public const string ArgumentOutOfRange_IndexLength = "Index and length must refer to a location within the string.";
+ public const string ArgumentOutOfRange_NeedNonNegNum = "Non-negative number required.";
- /// <summary>
- /// Gets the value associated with the specified key.
- /// </summary>
- /// <param name="map">this map</param>
- /// <param name="key">The key of the value to get.</param>
- /// <param name="value">When this method returns, contains the value associated with the specified key,
- /// if the key is found; otherwise, the default value for the type of the value parameter.
- /// This parameter is passed uninitialized.</param>
- /// <returns><c>true</c> if the <see cref="CharArrayMap{TValue}"/> contains an element with the specified key; otherwise, <c>false</c>.</returns>
- [CLSCompliant(false)]
- public static bool TryGetValue<TValue>(this CharArrayMap<TValue> map, ushort key, out TValue value)
- {
- return map.TryGetValue(key.ToString(CultureInfo.InvariantCulture), out value);
- }
+ public const string InvalidOperation_EnumFailedVersion = "Collection was modified after the enumerator was instantiated.";
+ public const string InvalidOperation_EnumOpCantHappen = "Enumeration has either not started or has already finished.";
-#endregion
+ public const string NotSupported_KeyCollectionSet = "Mutating a text collection derived from a dictionary is not allowed.";
+ public const string NotSupported_ReadOnlyCollection = "Collection is read-only.";
+ public const string NotSupported_ValueCollectionSet = "Mutating a value collection derived from a dictionary is not allowed.";
}
}
\ No newline at end of file
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArraySet.cs b/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArraySet.cs
index 538fca235..d2b1009de 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArraySet.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArraySet.cs
@@ -1,16 +1,18 @@
// Lucene version compatibility level 4.8.1
-using J2N.Globalization;
using J2N.Text;
+using Lucene.Net.Support;
using Lucene.Net.Util;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
+using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Text;
using JCG = J2N.Collections.Generic;
+#nullable enable
namespace Lucene.Net.Analysis.Util
{
@@ -63,51 +65,146 @@ namespace Lucene.Net.Analysis.Util
/// The <see cref="GetEnumerator()"/> returns an <see cref="T:IEnumerator{char[]}"/>
/// </para>
/// </summary>
- public class CharArraySet : ISet<string>
+ [DebuggerDisplay("Count = {Count}, Values = {ToString()}")]
+ public class CharArraySet : ISet<string>, ICollection<string>, ICollection, IReadOnlyCollection<string>
+#if FEATURE_READONLYSET
+ , IReadOnlySet<string>
+#endif
{
[SuppressMessage("Performance", "IDE0079:Remove unnecessary suppression", Justification = "This is a SonarCloud issue")]
[SuppressMessage("Performance", "S3887:Use an immutable collection or reduce the accessibility of the non-private readonly field", Justification = "Collection is immutable")]
[SuppressMessage("Performance", "S2386:Use an immutable collection or reduce the accessibility of the public static field", Justification = "Collection is immutable")]
- public static readonly CharArraySet EMPTY_SET = new CharArraySet(CharArrayMap<string>.EmptyMap());
- // LUCENENET: PLACEHOLDER moved to CharArrayMap
+ public static readonly CharArraySet Empty = new CharArraySet(CharArrayDictionary<object>.Empty);
- internal readonly ICharArrayMap map;
+ [Obsolete("Use Empty instead. This field will be removed in 4.8.0 release candidate."), EditorBrowsable(EditorBrowsableState.Never)]
+ public static CharArraySet EMPTY_SET => Empty;
+
+ // LUCENENET: PLACEHOLDER moved to CharArrayDictionary
+
+ internal readonly ICharArrayDictionary map;
+
+ private const int DefaultSetSize = 8; // LUCENENET specific
/// <summary>
- /// Create set with enough capacity to hold <paramref name="startSize"/> terms
+ /// Create set with enough capacity to hold <paramref name="capacity"/> terms
/// </summary>
/// <param name="matchVersion">
/// compatibility match version see <see cref="CharArraySet"/> for details. </param>
- /// <param name="startSize">
+ /// <param name="capacity">
/// the initial capacity </param>
/// <param name="ignoreCase">
/// <c>false</c> if and only if the set should be case sensitive
/// otherwise <c>true</c>. </param>
- public CharArraySet(LuceneVersion matchVersion, int startSize, bool ignoreCase)
- : this(new CharArrayMap<object>(matchVersion, startSize, ignoreCase))
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is less than zero.</exception>
+ public CharArraySet(LuceneVersion matchVersion, int capacity, bool ignoreCase)
+ : this(new CharArrayDictionary<object>(matchVersion, capacity, ignoreCase))
{
}
/// <summary>
- /// Creates a set from a collection of objects.
+ /// Creates a set from a collection of <see cref="string"/>s.
/// </summary>
/// <param name="matchVersion">
- /// compatibility match version see <see cref="CharArraySet"/> for details. </param>
- /// <param name="c">
- /// a collection whose elements to be placed into the set </param>
+ /// Compatibility match version see <see cref="CharArraySet"/> for details. </param>
+ /// <param name="collection">
+ /// A collection whose elements to be placed into the set. </param>
+ /// <param name="ignoreCase">
+ /// <c>false</c> if and only if the set should be case sensitive
+ /// otherwise <c>true</c>. </param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// A given element within the <paramref name="collection"/> is <c>null</c>.
+ /// </exception>
+ public CharArraySet(LuceneVersion matchVersion, IEnumerable<string> collection, bool ignoreCase)
+ : this(matchVersion, collection is ICollection<string> c ? c.Count : DefaultSetSize, ignoreCase)
+ {
+ // LUCENENET: Added guard clause
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ foreach (string text in collection)
+ {
+ // LUCENENET: S1699: Don't call call protected members in the constructor
+ map.Set(text);
+ }
+ }
+
+ /// <summary>
+ /// Creates a set from a collection of <see cref="T:char[]"/>s.
+ /// <para/>
+ /// <b>NOTE:</b> If <paramref name="ignoreCase"/> is <c>true</c>, the text arrays will be directly modified.
+ /// The user should never modify these text arrays after calling this method.
+ /// </summary>
+ /// <param name="matchVersion">
+ /// Compatibility match version see <see cref="CharArraySet"/> for details. </param>
+ /// <param name="collection">
+ /// A collection whose elements to be placed into the set. </param>
+ /// <param name="ignoreCase">
+ /// <c>false</c> if and only if the set should be case sensitive
+ /// otherwise <c>true</c>. </param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// A given element within the <paramref name="collection"/> is <c>null</c>.
+ /// </exception>
+ public CharArraySet(LuceneVersion matchVersion, IEnumerable<char[]> collection, bool ignoreCase)
+ : this(matchVersion, collection is ICollection<char[]> c ? c.Count : DefaultSetSize, ignoreCase)
+ {
+ // LUCENENET: Added guard clause
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ foreach (char[] text in collection)
+ {
+ // LUCENENET: S1699: Don't call call protected members in the constructor
+ map.Set(text);
+ }
+ }
+
+ /// <summary>
+ /// Creates a set from a collection of <see cref="ICharSequence"/>s.
+ /// </summary>
+ /// <param name="matchVersion">
+ /// Compatibility match version see <see cref="CharArraySet"/> for details. </param>
+ /// <param name="collection">
+ /// A collection whose elements to be placed into the set. </param>
/// <param name="ignoreCase">
/// <c>false</c> if and only if the set should be case sensitive
/// otherwise <c>true</c>. </param>
- public CharArraySet(LuceneVersion matchVersion, ICollection<string> c, bool ignoreCase)
- : this(matchVersion, c.Count, ignoreCase)
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// A given element within the <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <see cref="ICharSequence.HasValue"/> property for a given element in the <paramref name="collection"/> returns <c>false</c>.
+ /// </exception>
+ public CharArraySet(LuceneVersion matchVersion, IEnumerable<ICharSequence> collection, bool ignoreCase)
+ : this(matchVersion, collection is ICollection<ICharSequence> c ? c.Count : DefaultSetSize, ignoreCase)
{
- this.UnionWith(c);
+ // LUCENENET: Added guard clause
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ foreach (ICharSequence text in collection)
+ {
+ // LUCENENET: S1699: Don't call call protected members in the constructor
+ map.Set(text);
+ }
}
/// <summary>
- /// Create set from the specified map (internal only), used also by <see cref="CharArrayMap{TValue}.Keys"/>
+ /// Create set from the specified map (internal only), used also by <see cref="CharArrayDictionary{TValue}.Keys"/>
/// </summary>
- internal CharArraySet(ICharArrayMap map)
+ internal CharArraySet(ICharArrayDictionary map)
{
this.map = map;
}
@@ -121,97 +218,135 @@ namespace Lucene.Net.Analysis.Util
}
/// <summary>
- /// <c>true</c> if the <paramref name="length"/> chars of <paramref name="text"/> starting at <paramref name="offset"/>
- /// are in the set
+ /// <c>true</c> if the <paramref name="length"/> chars of <paramref name="text"/> starting at <paramref name="startIndex"/>
+ /// are in the set.
/// </summary>
- public virtual bool Contains(char[] text, int offset, int length)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref name="length"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="startIndex"/> and <paramref name="length"/> refer to a position outside of <paramref name="text"/>.</exception>
+ public virtual bool Contains(char[] text, int startIndex, int length)
{
- return map.ContainsKey(text, offset, length);
+ return map.ContainsKey(text, startIndex, length);
}
/// <summary>
/// <c>true</c> if the <see cref="T:char[]"/>s
/// are in the set
/// </summary>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
public virtual bool Contains(char[] text)
{
+ if (text is null)
+ throw new ArgumentNullException(nameof(text));
+
return map.ContainsKey(text, 0, text.Length);
}
/// <summary>
- /// <c>true</c> if the <see cref="ICharSequence"/> is in the set
+ /// <c>true</c> if the <see cref="ICharSequence"/> is in the set.
/// </summary>
- public virtual bool Contains(ICharSequence cs)
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="text"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <paramref name="text"/>'s <see cref="ICharSequence.HasValue"/> property returns <c>false</c>.
+ /// </exception>
+ public virtual bool Contains(ICharSequence text)
{
- return map.ContainsKey(cs);
+ return map.ContainsKey(text);
}
/// <summary>
- /// <c>true</c> if the <see cref="string"/> is in the set
+ /// <c>true</c> if the <see cref="string"/> is in the set.
/// </summary>
- public virtual bool Contains(string cs)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ public virtual bool Contains(string text)
{
- return map.ContainsKey(cs);
+ return map.ContainsKey(text);
}
/// <summary>
- /// <c>true</c> if the <see cref="object.ToString()"/> representation of <paramref name="o"/> is in the set
+ /// <c>true</c> if the <see cref="object.ToString()"/> representation of <paramref name="text"/> is in the set.
/// </summary>
- public virtual bool Contains(object o)
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ public virtual bool Contains<T>(T text)
{
- return map.ContainsKey(o);
+ return map.ContainsKey(text);
}
/// <summary>
- /// Add the <see cref="object.ToString()"/> representation of <paramref name="o"/> into the set.
+ /// Adds the <see cref="object.ToString()"/> representation of <paramref name="text"/> into the set.
/// The <see cref="object.ToString()"/> method is called after setting the thread to <see cref="CultureInfo.InvariantCulture"/>.
- /// If the type of <paramref name="o"/> is a value type, it will be converted using the
+ /// If the type of <paramref name="text"/> is a value type, it will be converted using the
/// <see cref="CultureInfo.InvariantCulture"/>.
/// </summary>
- /// <param name="o">A string-able object</param>
- /// <returns><c>true</c> if <paramref name="o"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- public virtual bool Add(object o)
+ /// <param name="text">A string-able object.</param>
+ /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ public virtual bool Add<T>(T text)
{
- return map.Put(o);
+ return map.Put(text);
}
/// <summary>
- /// Add this <see cref="ICharSequence"/> into the set
+ /// Adds a <see cref="ICharSequence"/> into the set
/// </summary>
- /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
+ /// <param name="text">The text to be added to the set.</param>
+ /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
public virtual bool Add(ICharSequence text)
{
return map.Put(text);
}
/// <summary>
- /// Add this <see cref="string"/> into the set
+ /// Adds a <see cref="string"/> into the set
/// </summary>
- /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
+ /// <param name="text">The text to be added to the set.</param>
+ /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
public virtual bool Add(string text)
{
return map.Put(text);
}
/// <summary>
- /// Add this <see cref="T:char[]"/> directly to the set.
- /// If <c>ignoreCase</c> is true for this <see cref="CharArraySet"/>, the text array will be directly modified.
+ /// Adds a <see cref="T:char[]"/> directly to the set.
+ /// <para/>
+ /// <b>NOTE:</b> If <c>ignoreCase</c> is <c>true</c> for this <see cref="CharArraySet"/>, the text array will be directly modified.
/// The user should never modify this text array after calling this method.
/// </summary>
- /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
+ /// <param name="text">The text to be added to the set.</param>
+ /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
public virtual bool Add(char[] text)
{
return map.Put(text);
}
/// <summary>
- /// LUCENENET specific for supporting <see cref="ICollection{T}"/>.
+ /// Adds a <see cref="T:char[]"/> to the set using the specified <paramref name="startIndex"/> and <paramref name="length"/>.
+ /// <para/>
+ /// <b>NOTE:</b> If <c>ignoreCase</c> is <c>true</c> for this <see cref="CharArraySet"/>, the text array will be directly modified.
/// </summary>
- void ICollection<string>.Add(string item)
+ /// <param name="text">The text to be added to the set.</param>
+ /// <param name="startIndex">The position of the <paramref name="text"/> where the target text begins.</param>
+ /// <param name="length">The total length of the <paramref name="text"/>.</param>
+ /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref name="length"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="startIndex"/> and <paramref name="length"/> refer to a position outside of <paramref name="text"/>.</exception>
+ public virtual bool Add(char[] text, int startIndex, int length)
{
- Add(item);
+ return map.Put(text, startIndex, length);
}
+ /// <summary>
+ /// LUCENENET specific for supporting <see cref="ICollection{T}"/>.
+ /// </summary>
+ void ICollection<string>.Add(string item) => Add(item);
+
/// <summary>
/// Gets the number of elements contained in the <see cref="CharArraySet"/>.
/// </summary>
@@ -220,7 +355,13 @@ namespace Lucene.Net.Analysis.Util
/// <summary>
/// <c>true</c> if the <see cref="CharArraySet"/> is read-only; otherwise <c>false</c>.
/// </summary>
- public virtual bool IsReadOnly { get; private set; }
+ public virtual bool IsReadOnly => map.IsReadOnly;
+
+ bool ICollection<string>.IsReadOnly => map.IsReadOnly;
+
+ bool ICollection.IsSynchronized => false;
+
+ object ICollection.SyncRoot => this;
/// <summary>
/// Returns an unmodifiable <see cref="CharArraySet"/>. This allows to provide
@@ -236,17 +377,17 @@ namespace Lucene.Net.Analysis.Util
{
if (set is null)
{
- throw new ArgumentNullException(nameof(set), "Given set is null"); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
+ throw new ArgumentNullException(nameof(set)); // LUCENENET specific - changed from IllegalArgumentException to ArgumentNullException (.NET convention)
}
- if (set == EMPTY_SET)
+ if (set == Empty)
{
- return EMPTY_SET;
+ return Empty;
}
- if (set.map is CharArrayMap.UnmodifiableCharArrayMap<object>)
+ if (set.map is CharArrayDictionary.ReadOnlyCharArrayDictionary<object>)
{
return set;
}
- return new CharArraySet(CharArrayMap.UnmodifiableMap<object>(set.map));
+ return new CharArraySet(CharArrayDictionary.UnmodifiableMap<object>(set.map));
}
/// <summary>
@@ -257,15 +398,67 @@ namespace Lucene.Net.Analysis.Util
// LUCENENET specific - allow .NET-like syntax for creating immutable collections
public virtual CharArraySet AsReadOnly()
{
- if (this == EMPTY_SET)
+ if (this == Empty)
{
- return EMPTY_SET;
+ return Empty;
}
- if (this.map is CharArrayMap.UnmodifiableCharArrayMap<object>)
+ if (this.map is CharArrayDictionary.ReadOnlyCharArrayDictionary<object>)
{
return this;
}
- return new CharArraySet(CharArrayMap.UnmodifiableMap<object>(this.map));
+ return new CharArraySet(CharArrayDictionary.UnmodifiableMap<object>(this.map));
+ }
+
+ /// <summary>
+ /// Returns a copy of this set as a new instance <see cref="CharArraySet"/>.
+ /// The <see cref="LuceneVersion"/> and <c>ignoreCase</c> property will be preserved.
+ /// </summary>
+ /// <returns>A copy of this set as a new instance of <see cref="CharArraySet"/>.
+ /// The <see cref="CharArrayDictionary{TValue}.ignoreCase"/> field as well as the
+ /// <see cref="CharArrayDictionary{TValue}.MatchVersion"/> will be preserved.</returns>
+ // LUCENENET specific - allow .NET-like syntax for copying CharArraySet
+ public virtual CharArraySet ToCharArraySet()
+ {
+ if (this == Empty)
+ {
+ return Empty;
+ }
+
+ return new CharArraySet(CharArrayDictionary.Copy<object>(this.map.MatchVersion, this.map));
+ }
+
+ /// <summary>
+ /// Returns a copy of this set as a new instance <see cref="CharArraySet"/>
+ /// with the provided <paramref name="matchVersion"/>.
+ /// The <c>ignoreCase</c> property will be preserved from this <see cref="CharArraySet"/>.
+ /// </summary>
+ /// <returns>A copy of this set as a new instance of <see cref="CharArraySet"/>.
+ /// The <see cref="CharArrayDictionary{TValue}.ignoreCase"/> field will be preserved.</returns>
+ // LUCENENET specific - allow .NET-like syntax for copying CharArraySet
+ public virtual CharArraySet ToCharArraySet(LuceneVersion matchVersion)
+ {
+ if (this == Empty)
+ {
+ return Empty;
+ }
+
+ return new CharArraySet(new CharArrayDictionary<object>(matchVersion, (IDictionary<string, object>)this.map, this.map.IgnoreCase));
+ }
+
+ /// <summary>
+ /// Returns a copy of this set as a new instance <see cref="CharArraySet"/>
+ /// with the provided <paramref name="matchVersion"/> and <paramref name="ignoreCase"/> values.
+ /// </summary>
+ /// <returns>A copy of this set as a new instance of <see cref="CharArraySet"/>.</returns>
+ // LUCENENET specific - allow .NET-like syntax for copying CharArraySet
+ public virtual CharArraySet ToCharArraySet(LuceneVersion matchVersion, bool ignoreCase)
+ {
+ if (this == Empty)
+ {
+ return Empty;
+ }
+
+ return new CharArraySet(new CharArrayDictionary<object>(matchVersion, (IDictionary<string, object>)this.map, ignoreCase));
}
/// <summary>
@@ -274,73 +467,250 @@ namespace Lucene.Net.Analysis.Util
/// <para>
/// <b>Note:</b> If you intend to create a copy of another <see cref="CharArraySet"/> where
/// the <see cref="LuceneVersion"/> of the source set differs from its copy
- /// <see cref="CharArraySet.CharArraySet(LuceneVersion, ICollection{string}, bool)"/> should be used instead.
- /// The <see cref="Copy{T}(LuceneVersion, ICollection{T})"/> will preserve the <see cref="LuceneVersion"/> of the
+ /// <see cref="CharArraySet.CharArraySet(LuceneVersion, IEnumerable{string}, bool)"/> should be used instead.
+ /// The <see cref="Copy{T}(LuceneVersion, IEnumerable{T})"/> method will preserve the <see cref="LuceneVersion"/> of the
/// source set it is an instance of <see cref="CharArraySet"/>.
/// </para>
/// </summary>
/// <param name="matchVersion">
/// compatibility match version. This argument will be ignored if the
/// given set is a <see cref="CharArraySet"/>. </param>
- /// <param name="set">
+ /// <param name="collection">
/// a set to copy </param>
- /// <returns> a copy of the given set as a <see cref="CharArraySet"/>. If the given set
- /// is a <see cref="CharArraySet"/> the <see cref="CharArrayMap{TValue}.ignoreCase"/> field as well as the
- /// <see cref="CharArrayMap{TValue}.MatchVersion"/> will be preserved. </returns>
- public static CharArraySet Copy<T>(LuceneVersion matchVersion, ICollection<T> set)
+ /// <returns> A copy of the given set as a <see cref="CharArraySet"/>. If the given set
+ /// is a <see cref="CharArraySet"/> the <see cref="CharArrayDictionary{TValue}.ignoreCase"/> field as well as the
+ /// <see cref="CharArrayDictionary{TValue}.MatchVersion"/> will be preserved. </returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// A given element within the <paramref name="collection"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <see cref="ICharSequence.HasValue"/> property for a given element in the <paramref name="collection"/> returns <c>false</c>.
+ /// </exception>
+ public static CharArraySet Copy<T>(LuceneVersion matchVersion, IEnumerable<T> collection)
{
- if (set == EMPTY_SET)
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ if (collection == Empty)
{
- return EMPTY_SET;
+ return Empty;
}
// LUCENENET NOTE: Testing for *is* is at least 10x faster
// than casting using *as* and then checking for null.
// http://stackoverflow.com/q/1583050/181087
- if (set is CharArraySet)
+ if (collection is CharArraySet source)
{
- var source = set as CharArraySet;
- return new CharArraySet(CharArrayMap.Copy<object>(source.map.MatchVersion, source.map));
+ return new CharArraySet(CharArrayDictionary.Copy<object>(source.map.MatchVersion, source.map));
}
- // Convert the elements in the collection to string in the invariant context.
- string[] stringSet;
- using (var context = new CultureContext(CultureInfo.InvariantCulture))
+ return CopySet(matchVersion, collection, ignoreCase: false);
+ }
+
+ internal static CharArraySet CopySet<T>(LuceneVersion matchVersion, IEnumerable<T> collection, bool ignoreCase)
+ {
+ if (collection is null)
+ throw new ArgumentNullException(nameof(collection));
+
+ if (collection is IEnumerable<string> stringCollection)
+ {
+ return new CharArraySet(matchVersion, stringCollection, ignoreCase);
+ }
+ else if (collection is IEnumerable<char[]> charArrayCollection)
{
- stringSet = set.Select(x => x.ToString()).ToArray(); // LUCENENET TODO: Performance - this approach can probably be improved
+ return new CharArraySet(matchVersion, charArrayCollection, ignoreCase);
+ }
+ else if (collection is IEnumerable<ICharSequence> charSequenceCollection)
+ {
+ return new CharArraySet(matchVersion, charSequenceCollection, ignoreCase);
}
- return new CharArraySet(matchVersion, stringSet, false);
+ return new CharArraySet(matchVersion, collection.Select(text =>
+ {
+ // We cannot capture Span<T> from outside of the lambda, so we just re-alocate the
+ // stack on every loop.
+ var returnType = CharArrayDictionary.ConvertObjectToChars(text, out char[] chars, out string s);
+ if (returnType == CharArrayDictionary.CharReturnType.String)
+ return s.ToCharArray();
+ else
+ return chars;
+ }), ignoreCase);
}
/// <summary>
- /// Returns an <see cref="IEnumerator"/> for <see cref="T:char[]"/> instances in this set.
+ /// Returns an enumerator that iterates through the <see cref="CharArraySet"/>.
/// </summary>
- public virtual IEnumerator GetEnumerator()
+ /// <returns>An enumerator that iterates through the <see cref="CharArraySet"/>.</returns>
+ /// <remarks>
+ /// An enumerator remains valid as long as the collection remains unchanged. If changes are made to
+ /// the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably
+ /// invalidated and the next call to <see cref="Enumerator.MoveNext()"/> or <see cref="IEnumerator.Reset()"/>
+ /// throws an <see cref="InvalidOperationException"/>.
+ /// <para/>
+ /// This method is an <c>O(log n)</c> operation.
+ /// </remarks>
+ public Enumerator GetEnumerator()
{
- // use the OriginalKeySet's enumerator (to not produce endless recursion)
- return map.OriginalKeySet.GetEnumerator();
+ // LUCENENET specific - Use custom Enumerator to prevent endless recursion
+ return new Enumerator(map);
}
- IEnumerator<string> IEnumerable<string>.GetEnumerator()
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+
+ IEnumerator<string> IEnumerable<string>.GetEnumerator() => GetEnumerator();
+
+ #region Nested Struct: Enumerator
+
+ /// <summary>
+ /// Enumerates the elements of a <see cref="CharArraySet"/> object.
+ /// <para/>
+ /// This implementation provides direct access to the <see cref="T:char[]"/> array of the underlying collection
+ /// as well as convenience properties for converting to <see cref="string"/> and <see cref="ICharSequence"/>.
+ /// </summary>
+ /// <remarks>
+ /// The <c>foreach</c> statement of the C# language (<c>for each</c> in C++, <c>For Each</c> in Visual Basic)
+ /// hides the complexity of enumerators. Therefore, using <c>foreach</c> is recommended instead of directly manipulating the enumerator.
+ /// <para/>
+ /// Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying collection.
+ /// <para/>
+ /// Initially, the enumerator is positioned before the first element in the collection. At this position, the
+ /// <see cref="Current"/> property is undefined. Therefore, you must call the
+ /// <see cref="MoveNext()"/> method to advance the enumerator to the first element
+ /// of the collection before reading the value of <see cref="Current"/>.
+ /// <para/>
+ /// The <see cref="Current"/> property returns the same object until
+ /// <see cref="MoveNext()"/> is called. <see cref="MoveNext()"/>
+ /// sets <see cref="Current"/> to the next element.
+ /// <para/>
+ /// If <see cref="MoveNext()"/> passes the end of the collection, the enumerator is
+ /// positioned after the last element in the collection and <see cref="MoveNext()"/>
+ /// returns <c>false</c>. When the enumerator is at this position, subsequent calls to <see cref="MoveNext()"/>
+ /// also return <c>false</c>. If the last call to <see cref="MoveNext()"/> returned false,
+ /// <see cref="Current"/> is undefined. You cannot set <see cref="Current"/>
+ /// to the first element of the collection again; you must create a new enumerator object instead.
+ /// <para/>
+ /// An enumerator remains valid as long as the collection remains unchanged. If changes are made to the collection,
+ /// such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and the next call
+ /// to <see cref="MoveNext()"/> or <see cref="IEnumerator.Reset()"/> throws an
+ /// <see cref="InvalidOperationException"/>.
+ /// <para/>
+ /// The enumerator does not have exclusive access to the collection; therefore, enumerating through a collection is
+ /// intrinsically not a thread-safe procedure. To guarantee thread safety during enumeration, you can lock the
+ /// collection during the entire enumeration. To allow the collection to be accessed by multiple threads for
+ /// reading and writing, you must implement your own synchronization.
+ /// <para/>
+ /// This method is an O(1) operation.
+ /// </remarks>
+ // LUCENENET specific.
+ public readonly struct Enumerator : IEnumerator<string>, IEnumerator
{
- // use the OriginalKeySet's enumerator (to not produce endless recursion)
- return (IEnumerator<string>)map.OriginalKeySet.GetEnumerator();
+ private readonly ICharArrayDictionaryEnumerator enumerator;
+
+ internal Enumerator(ICharArrayDictionary map)
+ {
+ this.enumerator = map.GetEnumerator();
+ }
+
+ /// <summary>
+ /// Gets the current value as a <see cref="CharArrayCharSequence"/>.
+ /// </summary>
+ // LUCENENET specific - quick access to ICharSequence interface
+ public ICharSequence CurrentValueCharSequence
+ => enumerator.CurrentKeyCharSequence;
+
+ /// <summary>
+ /// Gets the current value... do not modify the returned char[].
+ /// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1819", Justification = "Lucene's design requires some writable array properties")]
+ [WritableArray]
+ public char[] CurrentValue => enumerator.CurrentKey;
+
+ /// <summary>
+ /// Gets the current value as a newly created <see cref="string"/> object.
+ /// </summary>
+ public string Current => enumerator.CurrentKeyString;
+
+ object IEnumerator.Current
+ {
+ get
+ {
+ if (enumerator.NotStartedOrEnded)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+
+ return Current;
+ }
+ }
+
+ /// <summary>
+ /// Releases all resources used by the <see cref="Enumerator"/>.
+ /// </summary>
+ public void Dispose()
+ {
+ enumerator.Dispose();
+ }
+
+ /// <summary>
+ /// Advances the enumerator to the next element of the <see cref="CharArraySet"/>.
+ /// </summary>
+ /// <returns><c>true</c> if the enumerator was successfully advanced to the next element;
+ /// <c>false</c> if the enumerator has passed the end of the collection.</returns>
+ /// <exception cref="InvalidOperationException">The collection was modified after the enumerator was created.</exception>
+ /// <remarks>
+ /// After an enumerator is created, the enumerator is positioned before the first element in the collection,
+ /// and the first call to the <see cref="MoveNext()"/> method advances the enumerator to the first element
+ /// of the collection.
+ /// <para/>
+ /// If <see cref="MoveNext()"/> passes the end of the collection, the enumerator is positioned after the last element in the
+ /// collection and <see cref="MoveNext()"/> returns <c>false</c>. When the enumerator is at this position,
+ /// subsequent calls to <see cref="MoveNext()"/> also return <c>false</c>.
+ /// <para/>
+ /// An enumerator remains valid as long as the collection remains unchanged. If changes are made to the
+ /// collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated
+ /// and the next call to <see cref="MoveNext()"/> or <see cref="IEnumerator.Reset()"/> throws an
+ /// <see cref="InvalidOperationException"/>.
+ /// </remarks>
+ public bool MoveNext()
+ {
+ return enumerator.MoveNext();
+ }
+
+ void IEnumerator.Reset() => enumerator.Reset();
}
+ #endregion Nested Struct: Enumerator
+
/// <summary>
- /// Returns a string that represents the current object. (Inherited from <see cref="object"/>.)
+ /// Returns a string that represents the current collection.
+ /// <para/>
+ /// The presentation has a specific format. It is enclosed by curly
+ /// brackets ("{}"). Keys and values are separated by '=',
+ /// KeyValuePairs are separated by ', ' (comma and space).
+ /// <c>null</c> values are represented as the string "null".
/// </summary>
+ /// <returns>A string that represents the current collection.</returns>
public override string ToString()
{
+ if (Count == 0)
+ return "[]";
+
var sb = new StringBuilder("[");
- foreach (var item in this)
+ using var iter = GetEnumerator();
+ while (iter.MoveNext())
{
if (sb.Length > 1)
{
sb.Append(", ");
}
- sb.Append(item);
+ var currentValue = iter.CurrentValue; // LUCENENET specific - avoid string allocations by using iter.CurrentValue instead of iter.Current
+ if (currentValue is not null)
+ sb.Append(currentValue);
+ else
+ sb.Append("null");
}
return sb.Append(']').ToString();
}
@@ -361,8 +731,10 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
/// <param name="obj">object to be compared for equality with this set</param>
/// <returns><c>true</c> if the specified object is equal to this set</returns>
- public override bool Equals(object obj)
+ public override bool Equals(object? obj)
{
+ if (obj is null)
+ return false;
if (obj is ISet<string> other)
return JCG.SetEqualityComparer<string>.Default.Equals(this, other);
return false;
@@ -389,190 +761,551 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
/// <param name="array">The one-dimensional <see cref="T:string[]"/> Array that is the destination of the
/// elements copied from <see cref="CharArraySet"/>. The Array must have zero-based indexing.</param>
- /// <param name="arrayIndex">The zero-based index in array at which copying begins.</param>
- public void CopyTo(string[] array, int arrayIndex)
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
+ /// <exception cref="ArgumentException">The number of elements in the source is greater
+ /// than the available space in the destination array.</exception>
+ public void CopyTo(string[] array)
+ {
+ CopyTo(array, 0, map.Count);
+ }
+
+ /// <summary>
+ /// Copies the entire <see cref="CharArraySet"/> to a one-dimensional <see cref="T:string[]"/> array,
+ /// starting at the specified index of the target array.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="T:string[]"/> Array that is the destination of the
+ /// elements copied from <see cref="CharArraySet"/>. The Array must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in array at which copying begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException">The number of elements in the source is greater
+ /// than the available space from <paramref name="index"/> to the end of the destination array.</exception>
+ public void CopyTo(string[] array, int index)
+ {
+ CopyTo(array, index, map.Count);
+ }
+
+ /// <summary>
+ /// Copies the entire <see cref="CharArraySet"/> to a one-dimensional <see cref="T:string[]"/> array,
+ /// starting at the specified index of the target array.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="T:string[]"/> Array that is the destination of the
+ /// elements copied from <see cref="CharArraySet"/>. The Array must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in array at which copying begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> or <paramref name="count"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="index"/> is greater than the length of the destination <paramref name="array"/>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// <paramref name="count"/> is greater than the available space from the <paramref name="index"/>
+ /// to the end of the destination <paramref name="array"/>.
+ /// </exception>
+ internal void CopyTo(string[] array, int index, int count)
{
- using (var iter = map.OriginalKeySet.GetEnumerator())
+ if (array is null)
+ throw new ArgumentNullException(nameof(array));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (count < 0)
+ throw new ArgumentOutOfRangeException(nameof(count), count, SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (index > array.Length || count > array.Length - index)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+
+ using var iter = GetEnumerator();
+ for (int i = index, numCopied = 0; numCopied < count && iter.MoveNext(); i++, numCopied++)
{
- for (int i = arrayIndex; iter.MoveNext(); i++)
- {
- array[i] = iter.Current;
- }
+ array[i] = iter.Current;
}
}
- [Obsolete("Not applicable in this class.")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
- public virtual bool Remove(string item) // LUCENENET TODO: API - make an explicit implementation that isn't public
+ /// <summary>
+ /// Copies the entire <see cref="CharArraySet"/> to a jagged <see cref="T:char[][]"/> array or <see cref="IList{T}"/> of type char[],
+ /// starting at the specified index of the target array.
+ /// </summary>
+ /// <param name="array">The jagged <see cref="T:char[][]"/> array or <see cref="IList{T}"/> of type char[] that is the destination of the
+ /// elements copied from <see cref="CharArraySet"/>. The Array must have zero-based indexing.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
+ /// <exception cref="ArgumentException">The number of elements in the source is greater
+ /// than the available space in the destination array.</exception>
+ public void CopyTo(IList<char[]> array)
{
- // LUCENENET NOTE: According to the documentation header, Remove should not be supported
- throw UnsupportedOperationException.Create();
+ CopyTo(array, 0, map.Count);
}
- // LUCENENET - Added to ensure equality checking works in tests
/// <summary>
- /// Determines whether the current set and the specified collection contain the same elements.
+ /// Copies the entire <see cref="CharArraySet"/> to a jagged <see cref="T:char[][]"/> array or <see cref="IList{T}"/> of type char[]
+ /// starting at the specified index of the target array.
/// </summary>
- /// <param name="other">The collection to compare to the current set.</param>
- /// <returns><c>true</c> if the current set is equal to other; otherwise, <c>false</c>.</returns>
- public virtual bool SetEquals(IEnumerable<string> other)
+ /// <param name="array">The jagged <see cref="T:char[][]"/> array or <see cref="IList{T}"/> of type char[] that is the destination of the
+ /// elements copied from <see cref="CharArraySet"/>. The Array must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in array at which copying begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException">The number of elements in the source is greater
+ /// than the available space from <paramref name="index"/> to the end of the destination array.</exception>
+ public void CopyTo(IList<char[]> array, int index)
{
- if (!(other is CharArraySet otherSet))
- return false;
-
- // Invoke the implementation on CharArrayMap that
- // tests the dictionaries to ensure they contain
- // the same keys and values.
- return this.map.Equals(otherSet.map);
+ CopyTo(array, index, map.Count);
}
/// <summary>
- /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- /// in itself, the specified collection, or both.
+ /// Copies the entire <see cref="CharArraySet"/> to a jagged <see cref="T:char[][]"/> array or <see cref="IList{T}"/> of type char[]
+ /// starting at the specified index of the target array.
/// </summary>
- /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- public virtual bool UnionWith(IEnumerable<char[]> other)
+ /// <param name="array">The jagged <see cref="T:char[][]"/> array or <see cref="IList{T}"/> of type char[] that is the destination of the
+ /// elements copied from <see cref="CharArraySet"/>. The Array must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in array at which copying begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> or <paramref name="count"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="index"/> is greater than the length of the destination <paramref name="array"/>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// <paramref name="count"/> is greater than the available space from the <paramref name="index"/>
+ /// to the end of the destination <paramref name="array"/>.
+ /// </exception>
+ internal void CopyTo(IList<char[]> array, int index, int count)
{
- if (other is null)
- {
- throw new ArgumentNullException(nameof(other));
- }
- if (IsReadOnly)
- {
- throw UnsupportedOperationException.Create("CharArraySet is readonly");
- }
- bool modified = false;
- foreach (var item in other)
+ if (array is null)
+ throw new ArgumentNullException(nameof(array));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (count < 0)
+ throw new ArgumentOutOfRangeException(nameof(count), count, SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (index > array.Count || count > array.Count - index)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+
+ using var iter = GetEnumerator();
+ for (int i = index, numCopied = 0; numCopied < count && iter.MoveNext(); i++, numCopied++)
{
- if (Add(item))
- {
- modified = true;
- }
+ array[i] = (char[])iter.CurrentValue.Clone();
}
- return modified;
}
/// <summary>
- /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- /// in itself, the specified collection, or both.
+ /// Copies the entire <see cref="CharArraySet"/> to a one-dimensional <see cref="T:ICharSequence[]"/> array,
+ /// starting at the specified index of the target array.
/// </summary>
- /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- public virtual bool UnionWith(IEnumerable<ICharSequence> other)
+ /// <param name="array">The one-dimensional <see cref="T:ICharSequence[]"/> Array that is the destination of the
+ /// elements copied from <see cref="CharArraySet"/>. The Array must have zero-based indexing.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
+ /// <exception cref="ArgumentException">The number of elements in the source is greater
+ /// than the available space in the destination array.</exception>
+ public void CopyTo(ICharSequence[] array)
{
- if (other is null)
- {
- throw new ArgumentNullException(nameof(other));
- }
- if (IsReadOnly)
- {
- throw UnsupportedOperationException.Create("CharArraySet is readonly");
- }
- bool modified = false;
- foreach (var item in other)
- {
- if (Add(item))
- {
- modified = true;
- }
- }
- return modified;
+ CopyTo(array, 0, map.Count);
}
/// <summary>
- /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- /// in itself, the specified collection, or both.
+ /// Copies the entire <see cref="CharArraySet"/> to a one-dimensional <see cref="T:ICharSequence[]"/> array,
+ /// starting at the specified index of the target array.
/// </summary>
- /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- public virtual void UnionWith(IEnumerable<string> other)
+ /// <param name="array">The one-dimensional <see cref="T:ICharSequence[]"/> Array that is the destination of the
+ /// elements copied from <see cref="CharArraySet"/>. The Array must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in array at which copying begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException">The number of elements in the source is greater
+ /// than the available space from <paramref name="index"/> to the end of the destination array.</exception>
+ public void CopyTo(ICharSequence[] array, int index)
{
- if (other is null)
+ CopyTo(array, index, map.Count);
+ }
+
+ /// <summary>
+ /// Copies the entire <see cref="CharArraySet"/> to a one-dimensional <see cref="T:ICharSequence[]"/> array,
+ /// starting at the specified index of the target array.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="T:ICharSequence[]"/> Array that is the destination of the
+ /// elements copied from <see cref="CharArraySet"/>. The Array must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in array at which copying begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> or <paramref name="count"/> is less than zero.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="index"/> is greater than the length of the destination <paramref name="array"/>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// <paramref name="count"/> is greater than the available space from the <paramref name="index"/>
+ /// to the end of the destination <paramref name="array"/>.
+ /// </exception>
+ internal void CopyTo(ICharSequence[] array, int index, int count)
+ {
+ if (array is null)
+ throw new ArgumentNullException(nameof(array));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (count < 0)
+ throw new ArgumentOutOfRangeException(nameof(count), count, SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (index > array.Length || count > array.Length - index)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+
+ using var iter = GetEnumerator();
+ for (int i = index, numCopied = 0; numCopied < count && iter.MoveNext(); i++, numCopied++)
{
- throw new ArgumentNullException(nameof(other));
+ array[i] = ((char[])iter.CurrentValue.Clone()).AsCharSequence();
}
- if (IsReadOnly)
+ }
+
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
+ void ICollection.CopyTo(Array array, int index)
+ {
+ if (array is null)
+ throw new ArgumentNullException(nameof(array));
+ if (array.Rank != 1)
+ throw new ArgumentException(SR.Arg_RankMultiDimNotSupported, nameof(array));
+
+ if (array.GetLowerBound(0) != 0)
{
- throw UnsupportedOperationException.Create("CharArraySet is readonly");
+ throw new ArgumentException(SR.Arg_NonZeroLowerBound, nameof(array));
}
- foreach (var item in other)
+
+ if (index < 0)
{
- Add(item);
+ throw new ArgumentOutOfRangeException(nameof(index), index, SR.ArgumentOutOfRange_NeedNonNegNum);
}
- }
- /// <summary>
- /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- /// in itself, the specified collection, or both.
- /// </summary>
- /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- public virtual bool UnionWith<T>(IEnumerable<T> other)
- {
- if (other is null)
+ if (array.Length - index < Count)
{
- throw new ArgumentNullException(nameof(other));
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
}
- if (IsReadOnly)
+
+ if (array is string[] strings)
{
- throw UnsupportedOperationException.Create("CharArraySet is readonly");
+ CopyTo(strings, index);
}
- bool modified = false;
- foreach (var item in other)
+ else if (array is IList<char[]> chars)
{
- if (item is char[])
- {
- if (Add(item as char[]))
- {
- modified = true;
- }
- continue;
+ CopyTo(chars, index);
+ }
+ else if (array is ICharSequence[] charSequences)
+ {
+ CopyTo(charSequences, index);
+ }
+ else
+ {
+ object?[]? objects = array as object[];
+ if (objects == null)
+ {
+ throw new ArgumentException(SR.Argument_InvalidArrayType, nameof(array));
+ }
+
+ try
+ {
+
+ foreach (var entry in this)
+ objects[index++] = entry;
+ }
+ catch (ArrayTypeMismatchException)
+ {
+ throw new ArgumentException(SR.Argument_InvalidArrayType, nameof(array));
+ }
+ }
+ }
+
+ bool ICollection<string>.Remove(string item)
+ {
+ // LUCENENET NOTE: According to the documentation header, Remove should not be supported
+ throw UnsupportedOperationException.Create();
+ }
+
+ // LUCENENET - Added to ensure equality checking works in tests
+ /// <summary>
+ /// Determines whether the current set and the specified collection contain the same elements.
+ /// </summary>
+ /// <param name="other">The collection to compare to the current set.</param>
+ /// <returns><c>true</c> if the current set is equal to other; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ public virtual bool SetEquals(IEnumerable<string> other)
+ {
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
+
+ if (other is CharArraySet charArraySet)
+ return this.map.Equals(charArraySet.map);
+
+ if (other is ICollection<string> otherAsCollection)
+ {
+ if (this.Count != otherAsCollection.Count)
+ return false;
+
+ // already confirmed that the sets have the same number of distinct elements, so if
+ // one is a superset of the other then they must be equal
+ return ContainsAllElements(otherAsCollection);
+ }
+
+ int otherCount = 0;
+ foreach (var local in other)
+ {
+ if (local is not null && !this.Contains(local))
+ {
+ return false;
+ }
+ otherCount++;
+ }
+ return this.Count == otherCount;
+ }
+
+ // LUCENENET - Added to ensure equality checking works in tests
+ /// <summary>
+ /// Determines whether the current set and the specified collection contain the same elements.
+ /// </summary>
+ /// <param name="other">The collection to compare to the current set.</param>
+ /// <returns><c>true</c> if the current set is equal to other; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ public virtual bool SetEquals(IEnumerable<char[]> other)
+ {
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
+
+ if (other is CharArraySet charArraySet)
+ return this.map.Equals(charArraySet.map);
+
+ if (other is ICollection<char[]> otherAsCollection)
+ {
+ if (this.Count != otherAsCollection.Count)
+ return false;
+
+ // already confirmed that the sets have the same number of distinct elements, so if
+ // one is a superset of the other then they must be equal
+ return ContainsAllElements(otherAsCollection);
+ }
+
+ int otherCount = 0;
+ foreach (var local in other)
+ {
+ if (local is not null && !this.Contains(local))
+ {
+ return false;
+ }
+ otherCount++;
+ }
+ return this.Count == otherCount;
+ }
+
+ // LUCENENET - Added to ensure equality checking works in tests
+ /// <summary>
+ /// Determines whether the current set and the specified collection contain the same elements.
+ /// </summary>
+ /// <param name="other">The collection to compare to the current set.</param>
+ /// <returns><c>true</c> if the current set is equal to other; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ public virtual bool SetEquals(IEnumerable<ICharSequence> other)
+ {
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
+
+ if (other is CharArraySet charArraySet)
+ return this.map.Equals(charArraySet.map);
+
+ if (other is ICollection<ICharSequence> otherAsCollection)
+ {
+ if (this.Count != otherAsCollection.Count)
+ return false;
+
+ // already confirmed that the sets have the same number of distinct elements, so if
+ // one is a superset of the other then they must be equal
+ return ContainsAllElements(otherAsCollection);
+ }
+
+ int otherCount = 0;
+ foreach (var local in other)
+ {
+ if (local is null || !local.HasValue || !this.Contains(local))
+ {
+ return false;
}
+ otherCount++;
+ }
+ return this.Count == otherCount;
+ }
+
+ // LUCENENET - Added to ensure equality checking works in tests
+ /// <summary>
+ /// Determines whether the current set and the specified collection contain the same elements.
+ /// </summary>
+ /// <param name="other">The collection to compare to the current set.</param>
+ /// <returns><c>true</c> if the current set is equal to other; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ public virtual bool SetEquals<T>(IEnumerable<T> other)
+ {
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
+
+ if (other is CharArraySet charArraySet)
+ return this.map.Equals(charArraySet.map);
+
+ if (other is ICollection<T> otherAsCollection)
+ {
+ if (this.Count != otherAsCollection.Count)
+ return false;
+
+ // already confirmed that the sets have the same number of distinct elements, so if
+ // one is a superset of the other then they must be equal
+ return ContainsAllElements(otherAsCollection);
+ }
- // Convert the item to a string in the invariant culture
- string stringItem;
- using (var context = new CultureContext(CultureInfo.InvariantCulture))
+ int otherCount = 0;
+ foreach (var local in other)
+ {
+ if (local is null || (local is ICharSequence charSequence && !charSequence.HasValue) || !this.Contains(local))
{
- stringItem = item.ToString();
+ return false;
}
+ otherCount++;
+ }
+ return this.Count == otherCount;
+ }
+
+ /// <summary>
+ /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
+ /// in itself, the specified collection, or both.
+ /// <para/>
+ /// <b>NOTE:</b> If <c>ignoreCase</c> is <c>true</c> for this <see cref="CharArraySet"/>, the text arrays will be directly modified.
+ /// The user should never modify these text arrays after calling this method.
+ /// </summary>
+ /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ /// <exception cref="NotSupportedException">This set instance is read-only.</exception>
+ public virtual bool UnionWith(IEnumerable<char[]> other)
+ {
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
+ if (IsReadOnly)
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+
+ bool modified = false;
+ foreach (var item in other)
+ {
+ modified |= Add(item);
+ }
+ return modified;
+ }
+
+ /// <summary>
+ /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
+ /// in itself, the specified collection, or both.
+ /// </summary>
+ /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="other"/> is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// A given element within the collection is <c>null</c>.
+ /// <para/>
+ /// -or-
+ /// <para/>
+ /// The <see cref="ICharSequence.HasValue"/> property for a given element in the collection returns <c>false</c>.
+ /// </exception>
+ /// <exception cref="NotSupportedException">This set instance is read-only.</exception>
+ public virtual bool UnionWith(IEnumerable<ICharSequence> other)
+ {
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
+ if (IsReadOnly)
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+
+ bool modified = false;
+ foreach (var item in other)
+ {
+ modified |= Add(item);
+ }
+ return modified;
+ }
+
+ /// <summary>
+ /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
+ /// in itself, the specified collection, or both.
+ /// </summary>
+ /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ /// <exception cref="NotSupportedException">This set instance is read-only.</exception>
+ public virtual bool UnionWith(IEnumerable<string> other)
+ {
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
+ if (IsReadOnly)
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+
+ bool modified = false;
+ foreach (var item in other)
+ {
+ modified |= Add(item);
+ }
+ return modified;
+ }
+
+ void ISet<string>.UnionWith(IEnumerable<string> other)
+ {
+ UnionWith(other);
+ }
+
+ /// <summary>
+ /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
+ /// in itself, the specified collection, or both.
+ /// </summary>
+ /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ /// <exception cref="NotSupportedException">This set instance is read-only.</exception>
+ public virtual bool UnionWith<T>(IEnumerable<T> other)
+ {
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
+ if (IsReadOnly)
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
+
+#if FEATURE_SPANFORMATTABLE
+ Span<char> buffer = stackalloc char[256];
+#else
+ Span<char> buffer = stackalloc char[1];
+#endif
- if (Add(stringItem))
+ bool modified = false;
+ foreach (var item in other)
+ {
+ if (item is char[] charArray)
{
- modified = true;
+ modified |= Add(charArray);
+ continue;
}
+
+ // Convert the item to chars in the invariant culture
+ var returnType = CharArrayDictionary.ConvertObjectToChars(item, out char[] chars, out string s, buffer);
+ if (returnType == CharArrayDictionary.CharReturnType.String)
+ modified |= Add(s);
+ else
+ modified |= Add(chars);
}
return modified;
}
// LUCENENET - no modifications should be made outside of original
// Java implmentation's methods.
- [Obsolete("Not applicable in this class.")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
- public void IntersectWith(IEnumerable<string> other) // LUCENENET TODO: API - make an explicit implementation that isn't public
+ void ISet<string>.IntersectWith(IEnumerable<string> other)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
// LUCENENET - no modifications should be made outside of original
// Java implmentation's methods.
- [Obsolete("Not applicable in this class.")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
- public void ExceptWith(IEnumerable<string> other) // LUCENENET TODO: API - make an explicit implementation that isn't public
+ void ISet<string>.ExceptWith(IEnumerable<string> other)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
// LUCENENET - no modifications should be made outside of original
// Java implmentation's methods.
- [Obsolete("Not applicable in this class.")]
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
- public void SymmetricExceptWith(IEnumerable<string> other) // LUCENENET TODO: API - make an explicit implementation that isn't public
+ void ISet<string>.SymmetricExceptWith(IEnumerable<string> other)
{
- throw UnsupportedOperationException.Create();
+ throw UnsupportedOperationException.Create(SR.NotSupported_ReadOnlyCollection);
}
/// <summary>
@@ -580,17 +1313,82 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
/// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
/// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a subset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
public virtual bool IsSubsetOf(IEnumerable<string> other)
{
if (other is null)
+ throw new ArgumentNullException(nameof(other));
+
+ if (this.Count == 0)
{
+ return true;
+ }
+ CharArraySet? set = other as CharArraySet;
+ if (set != null)
+ {
+ if (this.Count > set.Count)
+ {
+ return false;
+ }
+ return this.IsSubsetOfCharArraySet(set);
+ }
+ // we just need to return true if the other set
+ // contains all of the elements of the this set,
+ // but we need to use the comparison rules of the current set.
+ this.GetFoundAndUnfoundCounts(other, out int foundCount, out int _);
+ return foundCount == this.Count;
+ }
+
+ /// <summary>
+ /// Determines whether a <see cref="CharArraySet"/> object is a subset of the specified collection.
+ /// </summary>
+ /// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a subset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
+ public virtual bool IsSubsetOf(IEnumerable<char[]> other)
+ {
+ if (other is null)
throw new ArgumentNullException(nameof(other));
+
+ if (this.Count == 0)
+ {
+ return true;
+ }
+ CharArraySet? set = other as CharArraySet;
+ if (set != null)
+ {
+ if (this.Count > set.Count)
+ {
+ return false;
+ }
+ return this.IsSubsetOfCharArraySet(set);
}
+ // we just need to return true if the other set
+ // contains all of the elements of the this set,
+ // but we need to use the comparison rules of the current set.
+ this.GetFoundAndUnfoundCounts(other, out int foundCount, out int _);
+ return foundCount == this.Count;
+ }
+
+ /// <summary>
+ /// Determines whether a <see cref="CharArraySet"/> object is a subset of the specified collection.
+ /// </summary>
+ /// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a subset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
+ public virtual bool IsSubsetOf(IEnumerable<ICharSequence> other)
+ {
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
+
if (this.Count == 0)
{
return true;
}
- CharArraySet set = other as CharArraySet;
+ CharArraySet? set = other as CharArraySet;
if (set != null)
{
if (this.Count > set.Count)
@@ -611,12 +1409,12 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
/// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
/// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a subset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
public virtual bool IsSubsetOf<T>(IEnumerable<T> other)
{
if (other is null)
- {
throw new ArgumentNullException(nameof(other));
- }
+
if (this.Count == 0)
{
return true;
@@ -633,26 +1431,83 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
/// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
/// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a superset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
public virtual bool IsSupersetOf(IEnumerable<string> other)
{
if (other is null)
+ throw new ArgumentNullException(nameof(other));
+
+ ICollection<string>? is2 = other as ICollection<string>;
+ if (is2 != null)
{
+ if (is2.Count == 0)
+ {
+ return true;
+ }
+ CharArraySet? set = other as CharArraySet;
+ if ((set != null) && (set.Count > this.Count))
+ {
+ return false;
+ }
+ }
+ return this.ContainsAllElements(other);
+ }
+
+ /// <summary>
+ /// Determines whether a <see cref="CharArraySet"/> object is a superset of the specified collection.
+ /// </summary>
+ /// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a superset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
+ public virtual bool IsSupersetOf(IEnumerable<char[]> other)
+ {
+ if (other is null)
throw new ArgumentNullException(nameof(other));
+
+ ICollection<char[]>? is2 = other as ICollection<char[]>;
+ if (is2 != null)
+ {
+ if (is2.Count == 0)
+ {
+ return true;
+ }
+ CharArraySet? set = other as CharArraySet;
+ if ((set != null) && (set.Count > this.Count))
+ {
+ return false;
+ }
}
- ICollection<string> is2 = other as ICollection<string>;
+ return this.ContainsAllElements(other);
+ }
+
+ /// <summary>
+ /// Determines whether a <see cref="CharArraySet"/> object is a superset of the specified collection.
+ /// </summary>
+ /// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a superset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
+ public virtual bool IsSupersetOf(IEnumerable<ICharSequence> other)
+ {
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
+
+ ICollection<ICharSequence>? is2 = other as ICollection<ICharSequence>;
if (is2 != null)
{
if (is2.Count == 0)
{
return true;
}
- CharArraySet set = other as CharArraySet;
+ CharArraySet? set = other as CharArraySet;
if ((set != null) && (set.Count > this.Count))
{
return false;
}
}
- return this.ContainsAll(other);
+ return this.ContainsAllElements(other);
}
/// <summary>
@@ -660,18 +1515,91 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
/// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
/// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a superset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
public virtual bool IsSupersetOf<T>(IEnumerable<T> other)
{
if (other is null)
- {
throw new ArgumentNullException(nameof(other));
- }
- ICollection<T> is2 = other as ICollection<T>;
+
+ ICollection<T>? is2 = other as ICollection<T>;
if (is2 != null && is2.Count == 0)
{
return true;
}
- return this.ContainsAll(other);
+ return this.ContainsAllElements(other);
+ }
+
+ /// <summary>
+ /// Determines whether a <see cref="CharArraySet"/> object is a proper subset of the specified collection.
+ /// </summary>
+ /// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a proper subset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
+ public virtual bool IsProperSubsetOf(IEnumerable<string> other)
+ {
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
+
+ ICollection<string>? is2 = other as ICollection<string>;
+ if (is2 != null)
+ {
+ if (this.Count == 0)
+ {
+ return (is2.Count > 0);
+ }
+ CharArraySet? set = other as CharArraySet;
+ if (set != null)
+ {
+ if (this.Count >= set.Count)
+ {
+ return false;
+ }
+ return this.IsSubsetOfCharArraySet(set);
+ }
+ }
+ // we just need to return true if the other set
+ // contains all of the elements of the this set plus at least one more,
+ // but we need to use the comparison rules of the current set.
+ this.GetFoundAndUnfoundCounts(other, out int foundCount, out int unfoundCount);
+ return foundCount == this.Count && unfoundCount > 0;
+ }
+
+ /// <summary>
+ /// Determines whether a <see cref="CharArraySet"/> object is a proper subset of the specified collection.
+ /// </summary>
+ /// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a proper subset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
+ public virtual bool IsProperSubsetOf(IEnumerable<char[]> other)
+ {
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
+
+ ICollection<char[]>? is2 = other as ICollection<char[]>;
+ if (is2 != null)
+ {
+ if (this.Count == 0)
+ {
+ return (is2.Count > 0);
+ }
+ CharArraySet? set = other as CharArraySet;
+ if (set != null)
+ {
+ if (this.Count >= set.Count)
+ {
+ return false;
+ }
+ return this.IsSubsetOfCharArraySet(set);
+ }
+ }
+ // we just need to return true if the other set
+ // contains all of the elements of the this set plus at least one more,
+ // but we need to use the comparison rules of the current set.
+ this.GetFoundAndUnfoundCounts(other, out int foundCount, out int unfoundCount);
+ return foundCount == this.Count && unfoundCount > 0;
}
/// <summary>
@@ -679,20 +1607,21 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
/// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
/// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a proper subset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
- public virtual bool IsProperSubsetOf(IEnumerable<string> other)
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
+ public virtual bool IsProperSubsetOf(IEnumerable<ICharSequence> other)
{
if (other is null)
- {
throw new ArgumentNullException(nameof(other));
- }
- ICollection<string> is2 = other as ICollection<string>;
+
+ ICollection<ICharSequence>? is2 = other as ICollection<ICharSequence>;
if (is2 != null)
{
if (this.Count == 0)
{
return (is2.Count > 0);
}
- CharArraySet set = other as CharArraySet;
+ CharArraySet? set = other as CharArraySet;
if (set != null)
{
if (this.Count >= set.Count)
@@ -714,13 +1643,14 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
/// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
/// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a proper subset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
public virtual bool IsProperSubsetOf<T>(IEnumerable<T> other)
{
if (other is null)
- {
throw new ArgumentNullException(nameof(other));
- }
- ICollection<T> is2 = other as ICollection<T>;
+
+ ICollection<T>? is2 = other as ICollection<T>;
if (is2 != null && this.Count == 0)
{
return (is2.Count > 0);
@@ -737,31 +1667,32 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
/// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
/// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a proper superset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
public virtual bool IsProperSupersetOf(IEnumerable<string> other)
{
if (other is null)
- {
throw new ArgumentNullException(nameof(other));
- }
+
if (this.Count == 0)
{
return false;
}
- ICollection<string> is2 = other as ICollection<string>;
+ ICollection<string>? is2 = other as ICollection<string>;
if (is2 != null)
{
if (is2.Count == 0)
{
return true;
}
- CharArraySet set = other as CharArraySet;
+ CharArraySet? set = other as CharArraySet;
if (set != null)
{
if (set.Count >= this.Count)
{
return false;
}
- return this.ContainsAll(set);
+ return this.ContainsAllElements(set);
}
}
this.GetFoundAndUnfoundCounts(other, out int foundCount, out int unfoundCount);
@@ -773,725 +1704,422 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
/// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
/// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a proper superset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
- public virtual bool IsProperSupersetOf<T>(IEnumerable<T> other)
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
+ public virtual bool IsProperSupersetOf(IEnumerable<char[]> other)
{
if (other is null)
- {
throw new ArgumentNullException(nameof(other));
- }
+
if (this.Count == 0)
{
return false;
}
- ICollection<T> is2 = other as ICollection<T>;
- if (is2 != null && is2.Count == 0)
+ ICollection<char[]>? is2 = other as ICollection<char[]>;
+ if (is2 != null)
{
- return true;
+ if (is2.Count == 0)
+ {
+ return true;
+ }
+ CharArraySet? set = other as CharArraySet;
+ if (set != null)
+ {
+ if (set.Count >= this.Count)
+ {
+ return false;
+ }
+ return this.ContainsAllElements(set);
+ }
}
this.GetFoundAndUnfoundCounts(other, out int foundCount, out int unfoundCount);
return foundCount < this.Count && unfoundCount == 0;
}
/// <summary>
- /// Determines whether the current <see cref="CharArraySet"/> object and a specified collection share common elements.
+ /// Determines whether a <see cref="CharArraySet"/> object is a proper superset of the specified collection.
/// </summary>
/// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
- /// <returns><c>true</c> if the <see cref="CharArraySet"/> object and <paramref name="other"/> share at least one common element; otherwise, <c>false</c>.</returns>
- public virtual bool Overlaps(IEnumerable<string> other)
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a proper superset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
+ public virtual bool IsProperSupersetOf(IEnumerable<ICharSequence> other)
{
if (other is null)
- {
throw new ArgumentNullException(nameof(other));
+
+ if (this.Count == 0)
+ {
+ return false;
}
- if (this.Count != 0)
+ ICollection<ICharSequence>? is2 = other as ICollection<ICharSequence>;
+ if (is2 != null)
{
- foreach (var local in other)
+ if (is2.Count == 0)
+ {
+ return true;
+ }
+ CharArraySet? set = other as CharArraySet;
+ if (set != null)
{
- if (this.Contains(local))
+ if (set.Count >= this.Count)
{
- return true;
+ return false;
}
+ return this.ContainsAllElements(set);
}
}
- return false;
+ this.GetFoundAndUnfoundCounts(other, out int foundCount, out int unfoundCount);
+ return foundCount < this.Count && unfoundCount == 0;
}
/// <summary>
- /// Determines whether the current <see cref="CharArraySet"/> object and a specified collection share common elements.
+ /// Determines whether a <see cref="CharArraySet"/> object is a proper superset of the specified collection.
/// </summary>
/// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> object and <paramref name="other"/> share at least one common element; otherwise, <c>false</c>.</returns>
- public virtual bool Overlaps<T>(IEnumerable<T> other)
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> object is a proper superset of <paramref name="other"/>; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ [SuppressMessage("Style", "IDE0019:Use pattern matching", Justification = "Following Microsoft's coding style")]
+ public virtual bool IsProperSupersetOf<T>(IEnumerable<T> other)
{
if (other is null)
- {
throw new ArgumentNullException(nameof(other));
- }
- if (this.Count != 0)
+
+ if (this.Count == 0)
{
- foreach (var local in other)
- {
- if (this.Contains(local))
- {
- return true;
- }
- }
+ return false;
}
- return false;
- }
-
- /// <summary>
- /// Returns <c>true</c> if this collection contains all of the elements
- /// in the specified collection.
- /// </summary>
- /// <param name="other">collection to be checked for containment in this collection</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> contains all of the elements in the specified collection; otherwise, <c>false</c>.</returns>
- public virtual bool ContainsAll(IEnumerable<string> other)
- {
- foreach (var local in other)
+ ICollection<T>? is2 = other as ICollection<T>;
+ if (is2 != null && is2.Count == 0)
{
- if (!this.Contains(local))
- {
- return false;
- }
+ return true;
}
- return true;
+ this.GetFoundAndUnfoundCounts(other, out int foundCount, out int unfoundCount);
+ return foundCount < this.Count && unfoundCount == 0;
}
/// <summary>
- /// Returns <c>true</c> if this collection contains all of the elements
- /// in the specified collection.
+ /// Determines whether the current <see cref="CharArraySet"/> object and a specified collection share common elements.
/// </summary>
- /// <param name="other">collection to be checked for containment in this collection</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> contains all of the elements in the specified collection; otherwise, <c>false</c>.</returns>
- public virtual bool ContainsAll<T>(IEnumerable<T> other)
- {
- foreach (var local in other)
- {
- if (!this.Contains(local))
- {
- return false;
- }
- }
- return true;
- }
-
- private bool IsSubsetOfCharArraySet(CharArraySet other)
+ /// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
+ /// <returns><c>true</c> if the <see cref="CharArraySet"/> object and <paramref name="other"/> share at least one common element; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ public virtual bool Overlaps(IEnumerable<string> other)
{
- foreach (var local in this)
- {
- if (!other.Contains(local))
- {
- return false;
- }
- }
- return true;
- }
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
- private void GetFoundAndUnfoundCounts<T>(IEnumerable<T> other, out int foundCount, out int unfoundCount)
- {
- foundCount = 0;
- unfoundCount = 0;
- foreach (var item in other)
+ if (this.Count != 0)
{
- if (this.Contains(item))
- {
- foundCount++;
- }
- else
+ foreach (var local in other)
{
- unfoundCount++;
- }
- }
- }
-
-#endregion
- }
-
- /// <summary>
- /// LUCENENET specific extension methods for CharArraySet
- /// </summary>
- public static class CharArraySetExtensions
- {
-#region Add
-
- /// <summary>
- /// Add this <see cref="bool"/> into the set
- /// </summary>
- /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- public static bool Add(this CharArraySet set, bool text)
- {
- return set.map.Put(text.ToString());
- }
-
- /// <summary>
- /// Add this <see cref="byte"/> into the set
- /// </summary>
- /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- public static bool Add(this CharArraySet set, byte text)
- {
- return set.map.Put(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// Add this <see cref="char"/> into the set
- /// </summary>
- /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- public static bool Add(this CharArraySet set, char text)
- {
- return set.map.Put("" + text);
- }
-
- ///// <summary>
- ///// Add this <see cref="decimal"/> into the set
- ///// </summary>
- ///// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- //public static bool Add(this CharArraySet set, decimal text)
- //{
- // return set.map.Put(text.ToString(CultureInfo.InvariantCulture));
- //}
-
- ///// <summary>
- ///// Add this <see cref="double"/> into the set
- ///// </summary>
- ///// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- //public static bool Add(this CharArraySet set, double text)
- //{
- // return set.map.Put(text.ToString(CultureInfo.InvariantCulture));
- //}
-
- ///// <summary>
- ///// Add this <see cref="float"/> into the set
- ///// </summary>
- ///// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- //public static bool Add(this CharArraySet set, float text)
- //{
- // return set.map.Put(text.ToString(CultureInfo.InvariantCulture));
- //}
-
- /// <summary>
- /// Add this <see cref="int"/> into the set
- /// </summary>
- /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- public static bool Add(this CharArraySet set, int text)
- {
- return set.map.Put(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// Add this <see cref="long"/> into the set
- /// </summary>
- /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- public static bool Add(this CharArraySet set, long text)
- {
- return set.map.Put(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// Add this <see cref="sbyte"/> into the set
- /// </summary>
- /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- [CLSCompliant(false)]
- public static bool Add(this CharArraySet set, sbyte text)
- {
- return set.map.Put(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// Add this <see cref="short"/> into the set
- /// </summary>
- /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- public static bool Add(this CharArraySet set, short text)
- {
- return set.map.Put(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// Add this <see cref="uint"/> into the set
- /// </summary>
- /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- [CLSCompliant(false)]
- public static bool Add(this CharArraySet set, uint text)
- {
- return set.map.Put(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// Add this <see cref="ulong"/> into the set
- /// </summary>
- /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- [CLSCompliant(false)]
- public static bool Add(this CharArraySet set, ulong text)
- {
- return set.map.Put(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// Add this <see cref="ushort"/> into the set
- /// </summary>
- /// <returns><c>true</c> if <paramref name="text"/> was added to the set; <c>false</c> if it already existed prior to this call</returns>
- [CLSCompliant(false)]
- public static bool Add(this CharArraySet set, ushort text)
- {
- return set.map.Put(text.ToString(CultureInfo.InvariantCulture));
- }
-
-#endregion
-
-#region Contains
-
- /// <summary>
- /// <c>true</c> if the <see cref="bool"/> is in the set
- /// </summary>
- public static bool Contains(this CharArraySet set, bool text)
- {
- return set.map.ContainsKey(text.ToString());
- }
-
- /// <summary>
- /// <c>true</c> if the <see cref="byte"/> is in the set
- /// </summary>
- public static bool Contains(this CharArraySet set, byte text)
- {
- return set.map.ContainsKey(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// <c>true</c> if the <see cref="char"/> is in the set
- /// </summary>
- public static bool Contains(this CharArraySet set, char text)
- {
- return set.map.ContainsKey("" + text);
- }
-
- ///// <summary>
- ///// <c>true</c> if the <see cref="decimal"/> is in the set
- ///// </summary>
- //public static bool Contains(this CharArraySet set, decimal text)
- //{
- // return set.map.ContainsKey(text.ToString(CultureInfo.InvariantCulture));
- //}
-
- ///// <summary>
- ///// <c>true</c> if the <see cref="double"/> is in the set
- ///// </summary>
- //public static bool Contains(this CharArraySet set, double text)
- //{
- // return set.map.ContainsKey(text.ToString(CultureInfo.InvariantCulture));
- //}
-
- ///// <summary>
- ///// <c>true</c> if the <see cref="float"/> is in the set
- ///// </summary>
- //public static bool Contains(this CharArraySet set, float text)
- //{
- // return set.map.ContainsKey(text.ToString(CultureInfo.InvariantCulture));
- //}
-
- /// <summary>
- /// <c>true</c> if the <see cref="int"/> is in the set
- /// </summary>
- public static bool Contains(this CharArraySet set, int text)
- {
- return set.map.ContainsKey(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// <c>true</c> if the <see cref="long"/> is in the set
- /// </summary>
- public static bool Contains(this CharArraySet set, long text)
- {
- return set.map.ContainsKey(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// <c>true</c> if the <see cref="sbyte"/> is in the set
- /// </summary>
- [CLSCompliant(false)]
- public static bool Contains(this CharArraySet set, sbyte text)
- {
- return set.map.ContainsKey(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// <c>true</c> if the <see cref="short"/> is in the set
- /// </summary>
- public static bool Contains(this CharArraySet set, short text)
- {
- return set.map.ContainsKey(text.ToString(CultureInfo.InvariantCulture));
- }
-
- /// <summary>
- /// <c>true</c> if the <see cref="uint"/> is in the set
- /// </summary>
- [CLSCompliant(false)]
- public static bool Contains(this CharArraySet set, uint text)
- {
- return set.map.ContainsKey(text.ToString(CultureInfo.InvariantCulture));
+ if (local is not null && this.Contains(local))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
}
/// <summary>
- /// <c>true</c> if the <see cref="ulong"/> is in the set
+ /// Determines whether the current <see cref="CharArraySet"/> object and a specified collection share common elements.
/// </summary>
- [CLSCompliant(false)]
- public static bool Contains(this CharArraySet set, ulong text)
+ /// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
+ /// <returns><c>true</c> if the <see cref="CharArraySet"/> object and <paramref name="other"/> share at least one common element; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ public virtual bool Overlaps(IEnumerable<char[]> other)
{
- return set.map.ContainsKey(text.ToString(CultureInfo.InvariantCulture));
- }
+ if (other is null)
+ throw new ArgumentNullException(nameof(other));
- /// <summary>
- /// <c>true</c> if the <see cref="ushort"/> is in the set
- /// </summary>
- [CLSCompliant(false)]
- public static bool Contains(this CharArraySet set, ushort text)
- {
- return set.map.ContainsKey(text.ToString(CultureInfo.InvariantCulture));
+ if (this.Count != 0)
+ {
+ foreach (var local in other)
+ {
+ if (local is not null && this.Contains(local))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
}
-#endregion
-
-#region UnionWith
-
/// <summary>
- /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- /// in itself, the specified collection, or both.
+ /// Determines whether the current <see cref="CharArraySet"/> object and a specified collection share common elements.
/// </summary>
- /// <param name="set">this <see cref="CharArraySet"/></param>
- /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- public static bool UnionWith(this CharArraySet set, IEnumerable<byte> other)
+ /// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
+ /// <returns><c>true</c> if the <see cref="CharArraySet"/> object and <paramref name="other"/> share at least one common element; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ public virtual bool Overlaps(IEnumerable<ICharSequence> other)
{
if (other is null)
- {
throw new ArgumentNullException(nameof(other));
- }
- if (set.IsReadOnly)
- {
- throw UnsupportedOperationException.Create("CharArraySet is readonly");
- }
- bool modified = false;
- foreach (var item in other)
+
+ if (this.Count != 0)
{
- if (set.Add(item.ToString(CultureInfo.InvariantCulture)))
+ foreach (var local in other)
{
- modified = true;
+ if (local is not null && local.HasValue && this.Contains(local))
+ {
+ return true;
+ }
}
}
- return modified;
+ return false;
}
/// <summary>
- /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- /// in itself, the specified collection, or both.
+ /// Determines whether the current <see cref="CharArraySet"/> object and a specified collection share common elements.
/// </summary>
- /// <param name="set">this <see cref="CharArraySet"/></param>
- /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- public static bool UnionWith(this CharArraySet set, IEnumerable<char> other)
+ /// <param name="other">The collection to compare to the current <see cref="CharArraySet"/> object.</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> object and <paramref name="other"/> share at least one common element; otherwise, <c>false</c>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="other"/> is <c>null</c>.</exception>
+ public virtual bool Overlaps<T>(IEnumerable<T> other)
{
if (other is null)
- {
throw new ArgumentNullException(nameof(other));
- }
- if (set.IsReadOnly)
- {
- throw UnsupportedOperationException.Create("CharArraySet is readonly");
- }
- bool modified = false;
- foreach (var item in other)
+
+ if (this.Count != 0)
{
- if (set.Add("" + item))
+ foreach (var local in other)
{
- modified = true;
+ if (local is not null && this.Contains(local))
+ {
+ return true;
+ }
}
}
- return modified;
+ return false;
}
- ///// <summary>
- ///// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- ///// in itself, the specified collection, or both.
- ///// </summary>
- ///// <param name="set">this <see cref="CharArraySet"/></param>
- ///// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- ///// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- //public static bool UnionWith(this CharArraySet set, IEnumerable<decimal> other)
- //{
- // if (other is null)
- // {
- // throw new ArgumentNullException(nameof(other));
- // }
- // if (set.IsReadOnly)
- // {
- // throw UnsupportedOperationException.Create("CharArraySet is readonly");
- // }
- // bool modified = false;
- // foreach (var item in other)
- // {
- // if (set.Add(item.ToString(CultureInfo.InvariantCulture)))
- // {
- // modified = true;
- // }
- // }
- // return modified;
- //}
-
- ///// <summary>
- ///// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- ///// in itself, the specified collection, or both.
- ///// </summary>
- ///// <param name="set">this <see cref="CharArraySet"/></param>
- ///// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- ///// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- //public static bool UnionWith(this CharArraySet set, IEnumerable<double> other)
- //{
- // if (other is null)
- // {
- // throw new ArgumentNullException(nameof(other));
- // }
- // if (set.IsReadOnly)
- // {
- // throw UnsupportedOperationException.Create("CharArraySet is readonly");
- // }
- // bool modified = false;
- // foreach (var item in other)
- // {
- // if (set.Add(item.ToString(CultureInfo.InvariantCulture)))
- // {
- // modified = true;
- // }
- // }
- // return modified;
- //}
-
- ///// <summary>
- ///// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- ///// in itself, the specified collection, or both.
- ///// </summary>
- ///// <param name="set">this <see cref="CharArraySet"/></param>
- ///// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- ///// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- //public static bool UnionWith(this CharArraySet set, IEnumerable<float> other)
- //{
- // if (other is null)
- // {
- // throw new ArgumentNullException(nameof(other));
- // }
- // if (set.IsReadOnly)
- // {
- // throw UnsupportedOperationException.Create("CharArraySet is readonly");
- // }
- // bool modified = false;
- // foreach (var item in other)
- // {
- // if (set.Add(item.ToString(CultureInfo.InvariantCulture)))
- // {
- // modified = true;
- // }
- // }
- // return modified;
- //}
-
/// <summary>
- /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- /// in itself, the specified collection, or both.
+ /// Returns <c>true</c> if this collection contains all of the elements
+ /// in the specified collection.
/// </summary>
- /// <param name="set">this <see cref="CharArraySet"/></param>
- /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- public static bool UnionWith(this CharArraySet set, IEnumerable<int> other)
+ /// <param name="other">collection to be checked for containment in this collection</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> contains all of the elements in the specified collection; otherwise, <c>false</c>.</returns>
+ [Obsolete("Use the IsSupersetOf() method instead. This method will be removed in 4.8.0 release candidate."), EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual bool ContainsAll(IEnumerable<string> other)
{
- if (other is null)
- {
- throw new ArgumentNullException(nameof(other));
- }
- if (set.IsReadOnly)
- {
- throw UnsupportedOperationException.Create("CharArraySet is readonly");
- }
- bool modified = false;
- foreach (var item in other)
+ foreach (var local in other)
{
- if (set.Add(item.ToString(CultureInfo.InvariantCulture)))
+ if (local is null || !this.Contains(local))
{
- modified = true;
+ return false;
}
}
- return modified;
+ return true;
}
/// <summary>
- /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- /// in itself, the specified collection, or both.
+ /// Returns <c>true</c> if this collection contains all of the elements
+ /// in the specified collection.
/// </summary>
- /// <param name="set">this <see cref="CharArraySet"/></param>
- /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- public static bool UnionWith(this CharArraySet set, IEnumerable<long> other)
+ /// <param name="other">collection to be checked for containment in this collection</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> contains all of the elements in the specified collection; otherwise, <c>false</c>.</returns>
+ [Obsolete("Use the IsSupersetOf() method instead. This method will be removed in 4.8.0 release candidate."), EditorBrowsable(EditorBrowsableState.Never)]
+ public virtual bool ContainsAll<T>(IEnumerable<T> other)
{
- if (other is null)
- {
- throw new ArgumentNullException(nameof(other));
- }
- if (set.IsReadOnly)
- {
- throw UnsupportedOperationException.Create("CharArraySet is readonly");
- }
- bool modified = false;
- foreach (var item in other)
+ foreach (var local in other)
{
- if (set.Add(item.ToString(CultureInfo.InvariantCulture)))
+ if (local is null || !this.Contains(local))
{
- modified = true;
+ return false;
}
}
- return modified;
+ return true;
}
/// <summary>
- /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- /// in itself, the specified collection, or both.
+ /// Returns <c>true</c> if this collection contains all of the elements
+ /// in the specified collection.
/// </summary>
- /// <param name="set">this <see cref="CharArraySet"/></param>
- /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- [CLSCompliant(false)]
- public static bool UnionWith(this CharArraySet set, IEnumerable<sbyte> other)
+ /// <param name="other">collection to be checked for containment in this collection</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> contains all of the elements in the specified collection; otherwise, <c>false</c>.</returns>
+ private bool ContainsAllElements(IEnumerable<string> other)
{
- if (other is null)
- {
- throw new ArgumentNullException(nameof(other));
- }
- if (set.IsReadOnly)
- {
- throw UnsupportedOperationException.Create("CharArraySet is readonly");
- }
- bool modified = false;
- foreach (var item in other)
+ foreach (var local in other)
{
- if (set.Add(item.ToString(CultureInfo.InvariantCulture)))
+ if (local is null || !this.Contains(local))
{
- modified = true;
+ return false;
}
}
- return modified;
+ return true;
}
/// <summary>
- /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- /// in itself, the specified collection, or both.
+ /// Returns <c>true</c> if this collection contains all of the elements
+ /// in the specified collection.
/// </summary>
- /// <param name="set">this <see cref="CharArraySet"/></param>
- /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- public static bool UnionWith(this CharArraySet set, IEnumerable<short> other)
+ /// <param name="other">collection to be checked for containment in this collection</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> contains all of the elements in the specified collection; otherwise, <c>false</c>.</returns>
+ private bool ContainsAllElements(IEnumerable<char[]> other)
{
- if (other is null)
- {
- throw new ArgumentNullException(nameof(other));
- }
- if (set.IsReadOnly)
- {
- throw UnsupportedOperationException.Create("CharArraySet is readonly");
- }
- bool modified = false;
- foreach (var item in other)
+ foreach (var local in other)
{
- if (set.Add(item.ToString(CultureInfo.InvariantCulture)))
+ if (local is null || !this.Contains(local))
{
- modified = true;
+ return false;
}
}
- return modified;
+ return true;
}
/// <summary>
- /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- /// in itself, the specified collection, or both.
+ /// Returns <c>true</c> if this collection contains all of the elements
+ /// in the specified collection.
/// </summary>
- /// <param name="set">this <see cref="CharArraySet"/></param>
- /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- [CLSCompliant(false)]
- public static bool UnionWith(this CharArraySet set, IEnumerable<uint> other)
+ /// <param name="other">collection to be checked for containment in this collection</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> contains all of the elements in the specified collection; otherwise, <c>false</c>.</returns>
+ private bool ContainsAllElements(IEnumerable<ICharSequence> other)
{
- if (other is null)
- {
- throw new ArgumentNullException(nameof(other));
- }
- if (set.IsReadOnly)
- {
- throw UnsupportedOperationException.Create("CharArraySet is readonly");
- }
- bool modified = false;
- foreach (var item in other)
+ foreach (var local in other)
{
- if (set.Add(item.ToString(CultureInfo.InvariantCulture)))
+ if (local is null || !local.HasValue || !this.Contains(local))
{
- modified = true;
+ return false;
}
}
- return modified;
+ return true;
}
/// <summary>
- /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- /// in itself, the specified collection, or both.
+ /// Returns <c>true</c> if this collection contains all of the elements
+ /// in the specified collection.
/// </summary>
- /// <param name="set">this <see cref="CharArraySet"/></param>
- /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- [CLSCompliant(false)]
- public static bool UnionWith(this CharArraySet set, IEnumerable<ulong> other)
+ /// <param name="other">collection to be checked for containment in this collection</param>
+ /// <returns><c>true</c> if this <see cref="CharArraySet"/> contains all of the elements in the specified collection; otherwise, <c>false</c>.</returns>
+ private bool ContainsAllElements<T>(IEnumerable<T> other)
{
- if (other is null)
+ foreach (var local in other)
{
- throw new ArgumentNullException(nameof(other));
+ if (local is null || (local is ICharSequence charSequence && !charSequence.HasValue) || !this.Contains(local))
+ {
+ return false;
+ }
}
- if (set.IsReadOnly)
+ return true;
+ }
+
+ private bool IsSubsetOfCharArraySet(CharArraySet other)
+ {
+ foreach (var local in this)
{
- throw UnsupportedOperationException.Create("CharArraySet is readonly");
+ if (local is null || !other.Contains(local))
+ {
+ return false;
+ }
}
- bool modified = false;
+ return true;
+ }
+
+ private void GetFoundAndUnfoundCounts(IEnumerable<string> other, out int foundCount, out int unfoundCount)
+ {
+ foundCount = 0;
+ unfoundCount = 0;
foreach (var item in other)
{
- if (set.Add(item.ToString(CultureInfo.InvariantCulture)))
+ if (item is not null && this.Contains(item))
+ {
+ foundCount++;
+ }
+ else
{
- modified = true;
+ unfoundCount++;
}
}
- return modified;
}
- /// <summary>
- /// Modifies the current <see cref="CharArraySet"/> to contain all elements that are present
- /// in itself, the specified collection, or both.
- /// </summary>
- /// <param name="set">this <see cref="CharArraySet"/></param>
- /// <param name="other">The collection whose elements should be merged into the <see cref="CharArraySet"/>.</param>
- /// <returns><c>true</c> if this <see cref="CharArraySet"/> changed as a result of the call</returns>
- [CLSCompliant(false)]
- public static bool UnionWith(this CharArraySet set, IEnumerable<ushort> other)
+ private void GetFoundAndUnfoundCounts(IEnumerable<char[]> other, out int foundCount, out int unfoundCount)
{
- if (other is null)
+ foundCount = 0;
+ unfoundCount = 0;
+ foreach (var item in other)
{
- throw new ArgumentNullException(nameof(other));
+ if (item is not null && this.Contains(item))
+ {
+ foundCount++;
+ }
+ else
+ {
+ unfoundCount++;
+ }
}
- if (set.IsReadOnly)
+ }
+
+ private void GetFoundAndUnfoundCounts(IEnumerable<ICharSequence> other, out int foundCount, out int unfoundCount)
+ {
+ foundCount = 0;
+ unfoundCount = 0;
+ foreach (var item in other)
{
- throw UnsupportedOperationException.Create("CharArraySet is readonly");
+ if (item is not null && item.HasValue && this.Contains(item))
+ {
+ foundCount++;
+ }
+ else
+ {
+ unfoundCount++;
+ }
}
- bool modified = false;
+ }
+
+ private void GetFoundAndUnfoundCounts<T>(IEnumerable<T> other, out int foundCount, out int unfoundCount)
+ {
+ foundCount = 0;
+ unfoundCount = 0;
foreach (var item in other)
{
- if (set.Add(item.ToString(CultureInfo.InvariantCulture)))
+ if (item is not null && this.Contains(item))
+ {
+ foundCount++;
+ }
+ else
{
- modified = true;
+ unfoundCount++;
}
}
- return modified;
}
#endregion
}
+
+ /// <summary>
+ /// Extensions to <see cref="IEnumerable{T}"/> for <see cref="CharArraySet"/>.
+ /// </summary>
+ // LUCENENET specific
+ public static class EnumerableExtensions
+ {
+ /// <summary>
+ /// Returns a copy of this <see cref="IEnumerable{T}"/> as a new instance of <see cref="CharArraySet"/> with the
+ /// specified <paramref name="matchVersion"/> and ignoreCase set to <c>false</c>.
+ /// </summary>
+ /// <typeparam name="T">The type of collection. Typically a <see cref="string"/> or <see cref="T:char[]"/>.</typeparam>
+ /// <param name="collection">This collection.</param>
+ /// <param name="matchVersion">Compatibility match version.</param>
+ /// <returns>A copy of this <see cref="IEnumerable{T}"/> as a <see cref="CharArraySet"/>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="collection"/> is <c>null</c>.</exception>
+ public static CharArraySet ToCharArraySet<T>(this IEnumerable<T> collection, LuceneVersion matchVersion)
+ {
+ return CharArraySet.CopySet(matchVersion, collection, ignoreCase: false);
+ }
+
+ /// <summary>
+ /// Returns a copy of this <see cref="IEnumerable{T}"/> as a new instance of <see cref="CharArraySet"/> with the
+ /// specified <paramref name="matchVersion"/> and <paramref name="ignoreCase"/>.
+ /// </summary>
+ /// <typeparam name="T">The type of collection. Typically a <see cref="string"/> or <see cref="T:char[]"/>.</typeparam>
+ /// <param name="collection">This collection.</param>
+ /// <param name="matchVersion">Compatibility match version.</param>
+ /// <param name="ignoreCase"><c>false</c> if and only if the set should be case sensitive otherwise <c>true</c>.</param>
+ /// <returns>A copy of this <see cref="IEnumerable{T}"/> as a <see cref="CharArraySet"/>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="collection"/> is <c>null</c>.</exception>
+ public static CharArraySet ToCharArraySet<T>(this IEnumerable<T> collection, LuceneVersion matchVersion, bool ignoreCase)
+ {
+ return CharArraySet.CopySet(matchVersion, collection, ignoreCase);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Util/StopwordAnalyzerBase.cs b/src/Lucene.Net.Analysis.Common/Analysis/Util/StopwordAnalyzerBase.cs
index 6e8970615..cded2217b 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Util/StopwordAnalyzerBase.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Util/StopwordAnalyzerBase.cs
@@ -56,7 +56,7 @@ namespace Lucene.Net.Analysis.Util
{
m_matchVersion = version;
// analyzers should use char array set for stopwords!
- this.m_stopwords = stopwords is null ? CharArraySet.EMPTY_SET : CharArraySet.Copy(version, stopwords).AsReadOnly();
+ this.m_stopwords = stopwords is null ? CharArraySet.Empty : CharArraySet.Copy(version, stopwords).AsReadOnly();
}
/// <summary>
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Util/WordlistLoader.cs b/src/Lucene.Net.Analysis.Common/Analysis/Util/WordlistLoader.cs
index 0834d0fd4..0385da530 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Util/WordlistLoader.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Util/WordlistLoader.cs
@@ -199,7 +199,7 @@ namespace Lucene.Net.Analysis.Util
/// </summary>
/// <returns> stem dictionary that overrules the stemming algorithm </returns>
/// <exception cref="IOException"> If there is a low-level I/O error. </exception>
- public static CharArrayMap<string> GetStemDict(TextReader reader, CharArrayMap<string> result)
+ public static CharArrayDictionary<string> GetStemDict(TextReader reader, CharArrayDictionary<string> result)
{
try
{
@@ -207,7 +207,7 @@ namespace Lucene.Net.Analysis.Util
while ((line = reader.ReadLine()) != null)
{
string[] wordstem = line.Split(new char[] { '\t' }, 2);
- result.Put(wordstem[0], wordstem[1]);
+ result[wordstem[0]] = wordstem[1];
}
}
finally
diff --git a/src/Lucene.Net.Analysis.Morfologik/Uk/UkrainianMorfologikAnalyzer.cs b/src/Lucene.Net.Analysis.Morfologik/Uk/UkrainianMorfologikAnalyzer.cs
index 681c15ab4..79217e973 100644
--- a/src/Lucene.Net.Analysis.Morfologik/Uk/UkrainianMorfologikAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Morfologik/Uk/UkrainianMorfologikAnalyzer.cs
@@ -91,7 +91,7 @@ namespace Lucene.Net.Analysis.Uk
/// <param name="matchVersion"><see cref="LuceneVersion"/> to match.</param>
/// <param name="stopwords">A stopword set.</param>
public UkrainianMorfologikAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Analysis.SmartCn/SmartChineseAnalyzer.cs b/src/Lucene.Net.Analysis.SmartCn/SmartChineseAnalyzer.cs
index 40da7a979..40890f3ca 100644
--- a/src/Lucene.Net.Analysis.SmartCn/SmartChineseAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.SmartCn/SmartChineseAnalyzer.cs
@@ -121,7 +121,7 @@ namespace Lucene.Net.Analysis.Cn.Smart
public SmartChineseAnalyzer(LuceneVersion matchVersion, bool useDefaultStopWords)
{
stopWords = useDefaultStopWords ? DefaultSetHolder.DEFAULT_STOP_SET
- : CharArraySet.EMPTY_SET;
+ : CharArraySet.Empty;
this.matchVersion = matchVersion;
}
@@ -137,7 +137,7 @@ namespace Lucene.Net.Analysis.Cn.Smart
/// <param name="stopWords"><see cref="CharArraySet"/> of stopwords to use.</param>
public SmartChineseAnalyzer(LuceneVersion matchVersion, CharArraySet stopWords)
{
- this.stopWords = stopWords ?? CharArraySet.EMPTY_SET;
+ this.stopWords = stopWords ?? CharArraySet.Empty;
this.matchVersion = matchVersion;
}
diff --git a/src/Lucene.Net.Analysis.Stempel/Pl/PolishAnalyzer.cs b/src/Lucene.Net.Analysis.Stempel/Pl/PolishAnalyzer.cs
index 505bb7da0..ac3dfaf77 100644
--- a/src/Lucene.Net.Analysis.Stempel/Pl/PolishAnalyzer.cs
+++ b/src/Lucene.Net.Analysis.Stempel/Pl/PolishAnalyzer.cs
@@ -115,7 +115,7 @@ namespace Lucene.Net.Analysis.Pl
/// <param name="matchVersion">lucene compatibility version</param>
/// <param name="stopwords">a stopword set</param>
public PolishAnalyzer(LuceneVersion matchVersion, CharArraySet stopwords)
- : this(matchVersion, stopwords, CharArraySet.EMPTY_SET)
+ : this(matchVersion, stopwords, CharArraySet.Empty)
{
}
diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Ar/TestArabicAnalyzer.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Ar/TestArabicAnalyzer.cs
index 65f41695c..f726e72a8 100644
--- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Ar/TestArabicAnalyzer.cs
+++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Ar/TestArabicAnalyzer.cs
@@ -96,12 +96,12 @@ namespace Lucene.Net.Analysis.Ar
public virtual void TestWithStemExclusionSet()
{
CharArraySet set = new CharArraySet(TEST_VERSION_CURRENT, AsSet("ساهدهات"), false);
- ArabicAnalyzer a = new ArabicAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET, set);
+ ArabicAnalyzer a = new ArabicAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty, set);
AssertAnalyzesTo(a, "كبيرة the quick ساهدهات", new string[] { "كبير", "the", "quick", "ساهدهات" });
AssertAnalyzesTo(a, "كبيرة the quick ساهدهات", new string[] { "كبير", "the", "quick", "ساهدهات" });
- a = new ArabicAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET, CharArraySet.EMPTY_SET);
+ a = new ArabicAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty, CharArraySet.Empty);
AssertAnalyzesTo(a, "كبيرة the quick ساهدهات", new string[] { "كبير", "the", "quick", "ساهد" });
AssertAnalyzesTo(a, "كبيرة the quick ساهدهات", new string[] { "كبير", "the", "quick", "ساهد" });
}
diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Bg/TestBulgarianAnalyzer.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Bg/TestBulgarianAnalyzer.cs
index 87e50e40e..d2c18767b 100644
--- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Bg/TestBulgarianAnalyzer.cs
+++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Bg/TestBulgarianAnalyzer.cs
@@ -46,7 +46,7 @@ namespace Lucene.Net.Analysis.Bg
[Test]
public virtual void TestCustomStopwords()
{
- Analyzer a = new BulgarianAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET);
+ Analyzer a = new BulgarianAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty);
AssertAnalyzesTo(a, "Как се казваш?", new string[] { "как", "се", "казваш" });
}
@@ -79,7 +79,7 @@ namespace Lucene.Net.Analysis.Bg
{
CharArraySet set = new CharArraySet(TEST_VERSION_CURRENT, 1, true);
set.add("строеве");
- Analyzer a = new BulgarianAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET, set);
+ Analyzer a = new BulgarianAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty, set);
AssertAnalyzesTo(a, "строевете строеве", new string[] { "строй", "строеве" });
}
diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Br/TestBrazilianStemmer.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Br/TestBrazilianStemmer.cs
index 9a12b9707..a5f0c6604 100644
--- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Br/TestBrazilianStemmer.cs
+++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Br/TestBrazilianStemmer.cs
@@ -141,7 +141,7 @@ namespace Lucene.Net.Analysis.Br
[Test]
public virtual void TestStemExclusionTable()
{
- BrazilianAnalyzer a = new BrazilianAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET, new CharArraySet(TEST_VERSION_CURRENT, AsSet("quintessência"), false));
+ BrazilianAnalyzer a = new BrazilianAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty, new CharArraySet(TEST_VERSION_CURRENT, AsSet("quintessência"), false));
checkReuse(a, "quintessência", "quintessência"); // excluded words will be completely unchanged.
}
diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Cjk/TestCJKAnalyzer.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Cjk/TestCJKAnalyzer.cs
index 13bfccad8..5ba502e36 100644
--- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Cjk/TestCJKAnalyzer.cs
+++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Cjk/TestCJKAnalyzer.cs
@@ -180,7 +180,7 @@ namespace Lucene.Net.Analysis.Cjk
{
Tokenizer tokenizer = new MockTokenizer(reader, MockTokenizer.WHITESPACE, false);
TokenFilter filter = new FakeStandardTokenizer(tokenizer);
- filter = new StopFilter(TEST_VERSION_CURRENT, filter, CharArraySet.EMPTY_SET);
+ filter = new StopFilter(TEST_VERSION_CURRENT, filter, CharArraySet.Empty);
filter = new CJKBigramFilter(filter);
return new TokenStreamComponents(tokenizer, filter);
});
diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Ckb/TestSoraniAnalyzer.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Ckb/TestSoraniAnalyzer.cs
index 48e2812a5..aa7d9df0d 100644
--- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Ckb/TestSoraniAnalyzer.cs
+++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Ckb/TestSoraniAnalyzer.cs
@@ -1,4 +1,4 @@
-// Lucene version compatibility level 4.8.1
+// Lucene version compatibility level 4.8.1
using Lucene.Net.Analysis.Util;
using NUnit.Framework;
@@ -46,7 +46,7 @@ namespace Lucene.Net.Analysis.Ckb
[Test]
public virtual void TestCustomStopwords()
{
- Analyzer a = new SoraniAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET);
+ Analyzer a = new SoraniAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty);
AssertAnalyzesTo(a, "ئەم پیاوە", new string[] { "ئەم", "پیاو" });
}
@@ -63,7 +63,7 @@ namespace Lucene.Net.Analysis.Ckb
{
CharArraySet set = new CharArraySet(TEST_VERSION_CURRENT, 1, true);
set.add("پیاوە");
- Analyzer a = new SoraniAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET, set);
+ Analyzer a = new SoraniAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty, set);
AssertAnalyzesTo(a, "پیاوە", new string[] { "پیاوە" });
}
diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Core/TestRandomChains.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Core/TestRandomChains.cs
index 391c9299f..a06ab1290 100644
--- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Core/TestRandomChains.cs
+++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Core/TestRandomChains.cs
@@ -304,7 +304,7 @@ namespace Lucene.Net.Analysis.Core
{ typeof(string), new StringArgProducer() },
{ typeof(NormalizeCharMap), new NormalizeCharMapArgProducer() },
{ typeof(CharacterRunAutomaton), new CharacterRunAutomatonArgProducer() },
- { typeof(CharArrayMap<string>), new StringCharArrayMapArgProducer() },
+ { typeof(CharArrayDictionary<string>), new StringCharArrayMapArgProducer() },
{ typeof(StemmerOverrideFilter.StemmerOverrideMap), new StemmerOverrideMapArgProducer() },
{ typeof(SynonymMap), new SynonymMapArgProducer() },
{ typeof(WordDelimiterFlags), new AnonymousProducer((random) => {
@@ -648,11 +648,11 @@ namespace Lucene.Net.Analysis.Core
public object Create(Random random)
{
int num = random.nextInt(10);
- CharArrayMap<string> map = new CharArrayMap<string>(TEST_VERSION_CURRENT, num, random.nextBoolean());
+ CharArrayDictionary<string> map = new CharArrayDictionary<string>(TEST_VERSION_CURRENT, num, random.nextBoolean());
for (int i = 0; i < num; i++)
{
// TODO: make nastier
- map.Put(TestUtil.RandomSimpleString(random), TestUtil.RandomSimpleString(random));
+ map[TestUtil.RandomSimpleString(random)] = TestUtil.RandomSimpleString(random);
}
return map;
}
diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Cz/TestCzechAnalyzer.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Cz/TestCzechAnalyzer.cs
index 8ad713fc0..bc97a4fbb 100644
--- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Cz/TestCzechAnalyzer.cs
+++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Cz/TestCzechAnalyzer.cs
@@ -69,7 +69,7 @@ namespace Lucene.Net.Analysis.Cz
{
CharArraySet set = new CharArraySet(TEST_VERSION_CURRENT, 1, true);
set.add("hole");
- CzechAnalyzer cz = new CzechAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET, set);
+ CzechAnalyzer cz = new CzechAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty, set);
AssertAnalyzesTo(cz, "hole desek", new string[] { "hole", "desk" });
}
diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/De/TestGermanAnalyzer.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/De/TestGermanAnalyzer.cs
index bae8101a9..2944ad7f8 100644
--- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/De/TestGermanAnalyzer.cs
+++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/De/TestGermanAnalyzer.cs
@@ -48,7 +48,7 @@ namespace Lucene.Net.Analysis.De
[Test]
public virtual void TestStemExclusionTable()
{
- GermanAnalyzer a = new GermanAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET, new CharArraySet(TEST_VERSION_CURRENT, AsSet("tischen"), false));
+ GermanAnalyzer a = new GermanAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty, new CharArraySet(TEST_VERSION_CURRENT, AsSet("tischen"), false));
CheckOneTerm(a, "tischen", "tischen");
}
diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Fr/TestFrenchAnalyzer.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Fr/TestFrenchAnalyzer.cs
index b6ff3d6e1..cb5108fb6 100644
--- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Fr/TestFrenchAnalyzer.cs
+++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Fr/TestFrenchAnalyzer.cs
@@ -1,4 +1,4 @@
-// Lucene version compatibility level 4.8.1
+// Lucene version compatibility level 4.8.1
using Lucene.Net.Analysis.Util;
using Lucene.Net.Util;
using NUnit.Framework;
@@ -135,10 +135,10 @@ namespace Lucene.Net.Analysis.Fr
{
CharArraySet set = new CharArraySet(TEST_VERSION_CURRENT, 1, true);
set.add("habitable");
- FrenchAnalyzer fa = new FrenchAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET, set);
+ FrenchAnalyzer fa = new FrenchAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty, set);
AssertAnalyzesTo(fa, "habitable chiste", new string[] { "habitable", "chist" });
- fa = new FrenchAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET, set);
+ fa = new FrenchAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty, set);
AssertAnalyzesTo(fa, "habitable chiste", new string[] { "habitable", "chist" });
}
diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Nl/TestDutchStemmer.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Nl/TestDutchStemmer.cs
index 310565a18..af5e212d7 100644
--- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Nl/TestDutchStemmer.cs
+++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Nl/TestDutchStemmer.cs
@@ -1,4 +1,4 @@
-// Lucene version compatibility level 4.8.1
+// Lucene version compatibility level 4.8.1
using System;
using NUnit.Framework;
using Lucene.Net.Analysis.Util;
@@ -151,10 +151,10 @@ namespace Lucene.Net.Analysis.Nl
CharArraySet set = new CharArraySet(LuceneVersion.LUCENE_30, 1, true);
#pragma warning restore 612, 618
set.add("lichamelijk");
- DutchAnalyzer a = new DutchAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET, set);
+ DutchAnalyzer a = new DutchAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty, set);
AssertAnalyzesTo(a, "lichamelijk lichamelijke", new string[] { "lichamelijk", "licham" });
- a = new DutchAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET, set);
+ a = new DutchAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty, set);
AssertAnalyzesTo(a, "lichamelijk lichamelijke", new string[] { "lichamelijk", "licham" });
}
@@ -166,7 +166,7 @@ namespace Lucene.Net.Analysis.Nl
[Test]
public virtual void TestStemOverrides()
{
- DutchAnalyzer a = new DutchAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET);
+ DutchAnalyzer a = new DutchAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty);
CheckOneTerm(a, "fiets", "fiets");
}
/// <summary>
@@ -178,14 +178,14 @@ namespace Lucene.Net.Analysis.Nl
{
DutchAnalyzer a = new DutchAnalyzer(LuceneVersion.LUCENE_30);
CheckOneTerm(a, "fiets", "fiets");
- a = new DutchAnalyzer(LuceneVersion.LUCENE_30, CharArraySet.EMPTY_SET);
+ a = new DutchAnalyzer(LuceneVersion.LUCENE_30, CharArraySet.Empty);
CheckOneTerm(a, "fiets", "fiet"); // only the default ctor populates the dict
}
[Test]
public virtual void TestEmptyStemDictionary()
{
- DutchAnalyzer a = new DutchAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET, CharArraySet.EMPTY_SET, CharArrayMap<string>.EmptyMap());
+ DutchAnalyzer a = new DutchAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty, CharArraySet.Empty, CharArrayDictionary<string>.Empty);
CheckOneTerm(a, "fiets", "fiet");
}
@@ -197,7 +197,7 @@ namespace Lucene.Net.Analysis.Nl
[Obsolete("(3.6) Remove this test in Lucene 5.0")]
public virtual void TestBuggyStemOverrides()
{
- DutchAnalyzer a = new DutchAnalyzer(LuceneVersion.LUCENE_35, CharArraySet.EMPTY_SET);
+ DutchAnalyzer a = new DutchAnalyzer(LuceneVersion.LUCENE_35, CharArraySet.Empty);
CheckOneTerm(a, "fiets", "fiet");
}
diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Synonym/TestSynonymMap.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Synonym/TestSynonymMap.cs
index 24fc697b0..d798f1d1f 100644
--- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Synonym/TestSynonymMap.cs
+++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Synonym/TestSynonymMap.cs
@@ -319,7 +319,7 @@ namespace Lucene.Net.Analysis.Synonym
private void AssertTokIncludes(SlowSynonymMap map, string src, string exp)
{
- Token[] tokens = map.Submap.Get(src).Synonyms;
+ Token[] tokens = map.Submap[src].Synonyms;
bool inc = false;
foreach (Token token in tokens)
{
@@ -333,7 +333,7 @@ namespace Lucene.Net.Analysis.Synonym
private SlowSynonymMap GetSubSynonymMap(SlowSynonymMap map, string src)
{
- return map.Submap.Get(src);
+ return map.Submap.TryGetValue(src, out SlowSynonymMap result) ? result : null;
}
}
}
\ No newline at end of file
diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Th/TestThaiAnalyzer.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Th/TestThaiAnalyzer.cs
index 78e064a4b..53c4b28ae 100644
--- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Th/TestThaiAnalyzer.cs
+++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Th/TestThaiAnalyzer.cs
@@ -53,7 +53,7 @@ namespace Lucene.Net.Analysis.Th
[Test]
public virtual void TestOffsets()
{
- AssertAnalyzesTo(new ThaiAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET), "การที่ได้ต้องแสดงว่างานดี", new string[] { "การ", "ที่", "ได้", "ต้อง", "แสดง", "ว่า", "งาน", "ดี" }, new int[] { 0, 3, 6, 9, 13, 17, 20, 23 }, new int[] { 3, 6, 9, 13, 17, 20, 23, 25 });
+ AssertAnalyzesTo(new ThaiAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty), "การที่ได้ต้องแสดงว่างานดี", new string[] { "การ", "ที่", "ได้", "ต้อง", "แสดง", "ว่า", "งาน", "ดี" }, new int[] { 0, 3, 6, 9, 13, 17, 20, 23 }, new int[] { 3, 6, 9, 13, 17, 20, 23, 25 });
}
[Test]
@@ -158,7 +158,7 @@ namespace Lucene.Net.Analysis.Th
[Test]
public virtual void TestReusableTokenStream()
{
- ThaiAnalyzer analyzer = new ThaiAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET);
+ ThaiAnalyzer analyzer = new ThaiAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty);
AssertAnalyzesTo(analyzer, "", new string[] { });
AssertAnalyzesTo(analyzer, "การที่ได้ต้องแสดงว่างานดี", new string[] { "การ", "ที่", "ได้", "ต้อง", "แสดง", "ว่า", "งาน", "ดี" });
@@ -392,7 +392,7 @@ namespace Lucene.Net.Analysis.Th
[Test]
public virtual void TestTwoSentences()
{
- AssertAnalyzesTo(new ThaiAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET), "This is a test. การที่ได้ต้องแสดงว่างานดี", new string[] { "this", "is", "a", "test", "การ", "ที่", "ได้", "ต้อง", "แสดง", "ว่า", "งาน", "ดี" }, new int[] { 0, 5, 8, 10, 16, 19, 22, 25, 29, 33, 36, 39 }, new int[] { 4, 7, 9, 14, 19, 22, 25, 29, 33, 36, 39, 41 });
+ AssertAnalyzesTo(new ThaiAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty), "This is a test. การที่ได้ต้องแสดงว่างานดี", new string[] { "this", "is", "a", "test", "การ", "ที่", "ได้", "ต้อง", "แสดง", "ว่า", "งาน", "ดี" }, new int[] { 0, 5, 8, 10, 16, 19, 22, 25, 29, 33, 36, 39 }, new int[] { 4, 7, 9, 14, 19, 22, 25, 29, 33, 36, 39, 41 });
}
/// <summary>
@@ -401,7 +401,7 @@ namespace Lucene.Net.Analysis.Th
[Test][LuceneNetSpecific]
public virtual void TestNumeralBreaking()
{
- ThaiAnalyzer analyzer = new ThaiAnalyzer(TEST_VERSION_CURRENT, CharArraySet.EMPTY_SET);
+ ThaiAnalyzer analyzer = new ThaiAnalyzer(TEST_VERSION_CURRENT, CharArraySet.Empty);
AssertAnalyzesTo(analyzer, "๑๒๓456", new String[] { "๑๒๓456" });
}
}
diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Util/TestCharArrayMap.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Util/TestCharArrayMap.cs
index 9cc53c11d..2e7085fec 100644
--- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Util/TestCharArrayMap.cs
+++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Util/TestCharArrayMap.cs
@@ -1,10 +1,15 @@
// Lucene version compatibility level 4.8.1
+using J2N.Collections;
+using J2N.Text;
using Lucene.Net.Analysis.Util;
+using Lucene.Net.Attributes;
using Lucene.Net.Support;
using Lucene.Net.Util;
using NUnit.Framework;
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
using System.Text;
using JCG = J2N.Collections.Generic;
@@ -32,7 +37,7 @@ namespace Lucene.Net.Analysis.Util
{
public virtual void DoRandom(int iter, bool ignoreCase)
{
- CharArrayMap<int?> map = new CharArrayMap<int?>(TEST_VERSION_CURRENT, 1, ignoreCase);
+ CharArrayDictionary<int?> map = new CharArrayDictionary<int?>(TEST_VERSION_CURRENT, 1, ignoreCase);
IDictionary<string, int?> hmap = new JCG.Dictionary<string, int?>();
char[] key;
@@ -49,16 +54,16 @@ namespace Lucene.Net.Analysis.Util
int val = Random.Next();
- object o1 = map.Put(key, val);
- object o2 = hmap.Put(hmapKey, val);
+ map.Put(key, val, out int? o1);
+ var o2 = hmap.Put(hmapKey, val);
assertEquals(o1, o2);
// add it again with the string method
- assertEquals(val, map.Put(keyStr, val));
+ assertEquals(val, map.Put(keyStr, val, out int? previousValue) ? null : previousValue);
- assertEquals(val, map.Get(key, 0, key.Length));
- assertEquals(val, map.Get(key));
- assertEquals(val, map.Get(keyStr));
+ assertEquals(val, map[key, 0, key.Length]); // LUCENENET: Changed Get() to this[]
+ assertEquals(val, map[key]); // LUCENENET: Changed Get() to this[]
+ assertEquals(val, map[keyStr]); // LUCENENET: Changed Get() to this[]
assertEquals(hmap.Count, map.size());
}
@@ -78,7 +83,7 @@ namespace Lucene.Net.Analysis.Util
[Test]
public virtual void TestMethods()
{
- CharArrayMap<int?> cm = new CharArrayMap<int?>(TEST_VERSION_CURRENT, 2, false);
+ CharArrayDictionary<int?> cm = new CharArrayDictionary<int?>(TEST_VERSION_CURRENT, 2, false);
Dictionary<string, int?> hm = new Dictionary<string, int?>();
hm["foo"] = 1;
hm["bar"] = 2;
@@ -88,8 +93,7 @@ namespace Lucene.Net.Analysis.Util
cm.PutAll(hm);
assertEquals(hm.Count, cm.Count);
- // LUCENENET: Need to cast here - no implicit conversion.
- CharArraySet cs = cm.Keys as CharArraySet;
+ CharArraySet cs = cm.Keys;
int n = 0;
foreach (string o in cs)
{
@@ -116,18 +120,16 @@ namespace Lucene.Net.Analysis.Util
cm.PutAll(hm);
assertEquals(hm.Count, cs.Count);
assertEquals(cm.Count, cs.Count);
- // LUCENENET: Need to cast here - no implicit conversion
- IEnumerator<KeyValuePair<string, int?>> iter1 = (IEnumerator<KeyValuePair<string, int?>>)cm.EntrySet().GetEnumerator();
+ CharArrayDictionary<int?>.Enumerator iter1 = cm.GetEnumerator();
n = 0;
while (iter1.MoveNext())
{
KeyValuePair<string, int?> entry = iter1.Current;
object key = entry.Key;
int? val = entry.Value;
- assertEquals(cm.Get(key), val);
- // LUCENENET: Need a cast to get to this method because it is not part of the IEnumerator<T> interface
- ((CharArrayMap<int?>.EntryIterator)iter1).SetValue(val * 100);
- assertEquals(val * 100, (int)cm.Get(key));
+ assertEquals(cm[key], val); // LUCENENET: Changed Get() to this[]
+ iter1.SetValue(val * 100);
+ assertEquals(val * 100, (int)cm[key]); // LUCENENET: Changed Get() to this[]
n++;
}
assertEquals(hm.Count, n);
@@ -135,7 +137,7 @@ namespace Lucene.Net.Analysis.Util
cm.PutAll(hm);
assertEquals(cm.size(), n);
- CharArrayMap<int?>.EntryIterator iter2 = cm.EntrySet().GetEnumerator() as CharArrayMap<int?>.EntryIterator;
+ CharArrayDictionary<int?>.Enumerator iter2 = cm.GetEnumerator();
n = 0;
while (iter2.MoveNext())
{
@@ -143,72 +145,73 @@ namespace Lucene.Net.Analysis.Util
int? val = iter2.Current.Value;
assertEquals(hm[keyc], val);
iter2.SetValue(val * 100);
- assertEquals(val * 100, (int)cm.Get(keyc));
+ assertEquals(val * 100, (int)cm[keyc]); // LUCENENET: Changed Get() to this[]
n++;
}
assertEquals(hm.Count, n);
- cm.EntrySet().Clear();
+ //cm.EntrySet().Clear(); // LUCENENET: Removed EntrySet() method because .NET uses the dictionary instance
+ cm.Clear();
assertEquals(0, cm.size());
- assertEquals(0, cm.EntrySet().size());
+ //assertEquals(0, cm.EntrySet().size()); // LUCENENET: Removed EntrySet() method because .NET uses the dictionary instance
assertTrue(cm.Count == 0);
}
[Test]
public void TestModifyOnUnmodifiable()
{
- CharArrayMap<int?> map = new CharArrayMap<int?>(TEST_VERSION_CURRENT, 2, false);
- map.Put("foo", 1);
- map.Put("bar", 2);
+ CharArrayDictionary<int?> map = new CharArrayDictionary<int?>(TEST_VERSION_CURRENT, 2, false);
+ map.Put("foo", 1, out _);
+ map.Put("bar", 2, out _);
int size = map.Count;
assertEquals(2, size);
assertTrue(map.ContainsKey("foo"));
- assertEquals(1, map.Get("foo"));
+ assertEquals(1, map["foo"]); // LUCENENET: Changed Get() to this[]
assertTrue(map.ContainsKey("bar"));
- assertEquals(2, map.Get("bar"));
+ assertEquals(2, map["bar"]); // LUCENENET: Changed Get() to this[]
map = map.AsReadOnly();
assertEquals("Map size changed due to unmodifiableMap call", size, map.Count);
var NOT_IN_MAP = "SirGallahad";
assertFalse("Test String already exists in map", map.ContainsKey(NOT_IN_MAP));
- assertNull("Test String already exists in map", map.Get(NOT_IN_MAP));
+ assertFalse("Test String already exists in map", map.TryGetValue(NOT_IN_MAP, out int? _)); // LUCENENET: Changed Get() to TryGetValue()
try
{
- map.Put(NOT_IN_MAP.ToCharArray(), 3);
+ map.Put(NOT_IN_MAP.ToCharArray(), 3, out _);
fail("Modified unmodifiable map");
}
catch (Exception e) when (e.IsUnsupportedOperationException())
{
// expected
assertFalse("Test String has been added to unmodifiable map", map.ContainsKey(NOT_IN_MAP));
- assertNull("Test String has been added to unmodifiable map", map.Get(NOT_IN_MAP));
+ assertFalse("Test String has been added to unmodifiable map", map.TryGetValue(NOT_IN_MAP, out int? _)); // LUCENENET: Changed Get() to TryGetValue()
assertEquals("Size of unmodifiable map has changed", size, map.Count);
}
try
{
- map.Put(NOT_IN_MAP, 3);
+ map.Put(NOT_IN_MAP, 3, out _);
fail("Modified unmodifiable map");
}
catch (Exception e) when (e.IsUnsupportedOperationException())
{
// expected
assertFalse("Test String has been added to unmodifiable map", map.ContainsKey(NOT_IN_MAP));
- assertNull("Test String has been added to unmodifiable map", map.Get(NOT_IN_MAP));
+ assertFalse("Test String has been added to unmodifiable map", map.TryGetValue(NOT_IN_MAP, out int? _)); // LUCENENET: Changed Get() to TryGetValue()
assertEquals("Size of unmodifiable map has changed", size, map.Count);
}
try
{
- map.Put(new StringBuilder(NOT_IN_MAP), 3);
+ map.Put(new StringBuilder(NOT_IN_MAP), 3, out _);
fail("Modified unmodifiable map");
}
catch (Exception e) when (e.IsUnsupportedOperationException())
{
// expected
assertFalse("Test String has been added to unmodifiable map", map.ContainsKey(NOT_IN_MAP));
- assertNull("Test String has been added to unmodifiable map", map.Get(NOT_IN_MAP));
+ assertFalse("Test String has been added to unmodifiable map", map.TryGetValue(NOT_IN_MAP, out int? _)); // LUCENENET: Changed Get() to TryGetValue()
assertEquals("Size of unmodifiable map has changed", size, map.Count);
}
@@ -222,20 +225,20 @@ namespace Lucene.Net.Analysis.Util
{
// expected
assertFalse("Test String has been added to unmodifiable map", map.ContainsKey(NOT_IN_MAP));
- assertNull("Test String has been added to unmodifiable map", map.Get(NOT_IN_MAP));
+ assertFalse("Test String has been added to unmodifiable map", map.TryGetValue(NOT_IN_MAP, out int? _)); // LUCENENET: Changed Get() to TryGetValue()
assertEquals("Size of unmodifiable map has changed", size, map.Count);
}
try
{
- map.Add(new KeyValuePair<string, int?>(NOT_IN_MAP, 3));
+ ((IDictionary<string, int?>)map).Add(new KeyValuePair<string, int?>(NOT_IN_MAP, 3));
fail("Modified unmodifiable map");
}
catch (Exception e) when (e.IsUnsupportedOperationException())
{
// expected
assertFalse("Test String has been added to unmodifiable map", map.ContainsKey(NOT_IN_MAP));
- assertNull("Test String has been added to unmodifiable map", map.Get(NOT_IN_MAP));
+ assertFalse("Test String has been added to unmodifiable map", map.TryGetValue(NOT_IN_MAP, out int? _)); // LUCENENET: Changed Get() to TryGetValue()
assertEquals("Size of unmodifiable map has changed", size, map.Count);
}
@@ -248,15 +251,13 @@ namespace Lucene.Net.Analysis.Util
{
// expected
assertFalse("Test String has been added to unmodifiable map", map.ContainsKey(NOT_IN_MAP));
- assertNull("Test String has been added to unmodifiable map", map.Get(NOT_IN_MAP));
+ assertFalse("Test String has been added to unmodifiable map", map.TryGetValue(NOT_IN_MAP, out int? _)); // LUCENENET: Changed Get() to TryGetValue()
assertEquals("Size of unmodifiable map has changed", size, map.Count);
}
try
{
-#pragma warning disable 612, 618
- map.Remove(new KeyValuePair<string, int?>("foo", 1));
-#pragma warning restore 612, 618
+ ((IDictionary<string, int?>)map).Remove(new KeyValuePair<string, int?>("foo", 1));
fail("Modified unmodifiable map");
}
catch (Exception e) when (e.IsUnsupportedOperationException())
@@ -279,7 +280,8 @@ namespace Lucene.Net.Analysis.Util
try
{
- map.EntrySet().Clear();
+ //map.EntrySet().Clear(); // LUCENENET: Removed EntrySet() method because .NET uses the dictionary instance
+ map.Clear();
fail("Modified unmodifiable map");
}
catch (Exception e) when (e.IsUnsupportedOperationException())
@@ -301,14 +303,14 @@ namespace Lucene.Net.Analysis.Util
try
{
- map.Put((object)NOT_IN_MAP, 3);
+ map.Put((object)NOT_IN_MAP, 3, out _);
fail("Modified unmodifiable map");
}
catch (Exception e) when (e.IsUnsupportedOperationException())
{
// expected
assertFalse("Test String has been added to unmodifiable map", map.ContainsKey(NOT_IN_MAP));
- assertNull("Test String has been added to unmodifiable map", map.Get(NOT_IN_MAP));
+ assertFalse("Test String has been added to unmodifiable map", map.TryGetValue(NOT_IN_MAP, out int? _)); // LUCENENET: Changed Get() to TryGetValue()
assertEquals("Size of unmodifiable map has changed", size, map.size());
}
@@ -321,29 +323,364 @@ namespace Lucene.Net.Analysis.Util
{
// expected
assertFalse("Test String has been added to unmodifiable map", map.ContainsKey(NOT_IN_MAP));
- assertNull("Test String has been added to unmodifiable map", map.Get(NOT_IN_MAP));
+ assertFalse("Test String has been added to unmodifiable map", map.TryGetValue(NOT_IN_MAP, out int? _)); // LUCENENET: Changed Get() to TryGetValue()
assertEquals("Size of unmodifiable map has changed", size, map.size());
}
assertTrue(map.ContainsKey("foo"));
- assertEquals(1, map.Get("foo"));
+ assertEquals(1, map["foo"]); // LUCENENET: Changed Get() to this[]
assertTrue(map.ContainsKey("bar"));
- assertEquals(2, map.Get("bar"));
+ assertEquals(2, map["bar"]); // LUCENENET: Changed Get() to this[]
}
[Test]
public virtual void TestToString()
{
- CharArrayMap<int?> cm = new CharArrayMap<int?>(TEST_VERSION_CURRENT, Collections.SingletonMap<string, int?>("test", 1), false);
+ CharArrayDictionary<int?> cm = new CharArrayDictionary<int?>(TEST_VERSION_CURRENT, Collections.SingletonMap<string, int?>("test", 1), false);
assertEquals("[test]", cm.Keys.ToString());
assertEquals("[1]", cm.Values.ToString());
- assertEquals("[test=1]", cm.EntrySet().ToString());
+ //assertEquals("[test=1]", cm.EntrySet().ToString()); // LUCENENET: Removed EntrySet() method because .NET uses the dictionary instance
assertEquals("{test=1}", cm.ToString());
- cm.Put("test2", 2);
+ cm["test2"] = 2; // LUCENENET: Changed Put() to this[]
assertTrue(cm.Keys.ToString().Contains(", "));
assertTrue(cm.Values.ToString().Contains(", "));
- assertTrue(cm.EntrySet().ToString().Contains(", "));
+ //assertTrue(cm.EntrySet().ToString().Contains(", ")); // LUCENENET: Removed EntrySet() method because .NET uses the dictionary instance
assertTrue(cm.ToString().Contains(", "));
}
+
+ [Test, LuceneNetSpecific]
+ public virtual void TestIsReadOnly()
+ {
+ CharArrayDictionary<int?> target = new CharArrayDictionary<int?>(TEST_VERSION_CURRENT, Collections.SingletonMap<string, int?>("test", 1), false);
+ CharArrayDictionary<int?> readOnlyTarget = target.AsReadOnly();
+
+ assertFalse(target.IsReadOnly);
+ assertTrue(target.Keys.IsReadOnly); // KeyCollection is always read-only
+ assertTrue(readOnlyTarget.IsReadOnly);
+ assertTrue(readOnlyTarget.Keys.IsReadOnly);
+ }
+
+ [Test, LuceneNetSpecific]
+ public virtual void TestEnumeratorExceptions()
+ {
+ CharArrayDictionary<int?> map = new CharArrayDictionary<int?>(TEST_VERSION_CURRENT, 3, ignoreCase: false)
+ {
+ ["foo"] = 0,
+ ["bar"] = 0,
+ ["baz"] = 0,
+ };
+
+ // Checks to ensure our Current property throws when outside of the enumeration
+ using (var iter = map.GetEnumerator())
+ {
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.Current; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.CurrentKey; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.CurrentKeyCharSequence; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.CurrentKeyString; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.CurrentValue; });
+
+ while (iter.MoveNext())
+ {
+ Assert.DoesNotThrow(() => { var _ = iter.Current; });
+ Assert.DoesNotThrow(() => { var _ = iter.CurrentKey; });
+ Assert.DoesNotThrow(() => { var _ = iter.CurrentKeyCharSequence; });
+ Assert.DoesNotThrow(() => { var _ = iter.CurrentKeyString; });
+ Assert.DoesNotThrow(() => { var _ = iter.CurrentValue; });
+ }
+
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.Current; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.CurrentKey; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.CurrentKeyCharSequence; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.CurrentKeyString; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.CurrentValue; });
+ }
+
+ using (var ours = map.GetEnumerator())
+ {
+ using var theirs = map.GetEnumerator();
+
+ assertTrue(ours.MoveNext());
+ Assert.DoesNotThrow(() => theirs.MoveNext());
+
+ assertTrue(ours.MoveNext());
+ ours.SetValue(1);
+ Assert.Throws<InvalidOperationException>(() => theirs.MoveNext());
+
+ Assert.DoesNotThrow(() => ours.MoveNext());
+ Assert.DoesNotThrow(() => ours.SetValue(1));
+ Assert.Throws<InvalidOperationException>(() => theirs.MoveNext());
+ }
+
+ using (var ours = map.GetEnumerator())
+ {
+ using var theirs = map.GetEnumerator();
+
+ assertTrue(ours.MoveNext());
+ ours.SetValue(1);
+ Assert.Throws<InvalidOperationException>(() => theirs.MoveNext());
+
+ Assert.DoesNotThrow(() => ours.MoveNext());
+ Assert.DoesNotThrow(() => { map["baz"] = 2; });
+ Assert.Throws<InvalidOperationException>(() => theirs.MoveNext());
+ Assert.Throws<InvalidOperationException>(() => ours.MoveNext());
+ }
+
+ using (var ours = map.GetEnumerator())
+ {
+ using var theirs = map.GetEnumerator();
+
+ assertTrue(ours.MoveNext());
+ ours.SetValue(1);
+ Assert.Throws<InvalidOperationException>(() => theirs.MoveNext());
+
+ Assert.DoesNotThrow(() => ours.MoveNext());
+ Assert.DoesNotThrow(() => { map.Clear(); });
+ Assert.Throws<InvalidOperationException>(() => theirs.MoveNext());
+ Assert.Throws<InvalidOperationException>(() => ours.MoveNext());
+
+ Assert.Throws<InvalidOperationException>(() => { var _ = ours.Current; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = ours.CurrentKey; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = ours.CurrentKeyCharSequence; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = ours.CurrentKeyString; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = ours.CurrentValue; });
+ }
+ }
+
+ [Test, LuceneNetSpecific]
+ public virtual void TestKeyCollectionEnumeratorExceptions()
+ {
+ var map = new CharArrayDictionary<int?>(TEST_VERSION_CURRENT, 3, ignoreCase: false)
+ {
+ ["foo"] = 0,
+ ["bar"] = 0,
+ ["baz"] = 0,
+ };
+
+
+ // Checks to ensure our Current property throws when outside of the enumeration
+ using (var iter = map.Keys.GetEnumerator())
+ {
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.Current; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.CurrentValue; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.CurrentValueCharSequence; });
+
+ while (iter.MoveNext())
+ {
+ Assert.DoesNotThrow(() => { var _ = iter.Current; });
+ Assert.DoesNotThrow(() => { var _ = iter.CurrentValue; });
+ Assert.DoesNotThrow(() => { var _ = iter.CurrentValueCharSequence; });
+ }
+
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.Current; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.CurrentValue; });
+ Assert.Throws<InvalidOperationException>(() => { var _ = iter.CurrentValueCharSequence; });
+ }
+
+ using (var ours = map.Keys.GetEnumerator())
... 1335 lines suppressed ...