/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections; /// /// This interface should be implemented by any class whose instances are intended /// to be executed by a thread. /// public interface IThreadRunnable { /// /// This method has to be implemented in order that starting of the thread causes the object's /// run method to be called in that separately executing thread. /// void Run(); } /// /// Contains conversion support elements such as classes, interfaces and static methods. /// public class SupportClass { public interface Checksum { void Reset(); void Update(int b); void Update(byte[] b); void Update(byte[] b, int offset, int length); Int64 GetValue(); } public class CRC32 : Checksum { private static readonly UInt32[] crcTable = InitializeCRCTable(); private static UInt32[] InitializeCRCTable() { UInt32[] crcTable = new UInt32[256]; for (UInt32 n = 0; n < 256; n++) { UInt32 c = n; for (int k = 8; --k >= 0; ) { if ((c & 1) != 0) c = 0xedb88320 ^ (c >> 1); else c = c >> 1; } crcTable[n] = c; } return crcTable; } private UInt32 crc = 0; public Int64 GetValue() { return (Int64)crc & 0xffffffffL; } public void Reset() { crc = 0; } public void Update(int bval) { UInt32 c = ~crc; c = crcTable[(c ^ bval) & 0xff] ^ (c >> 8); crc = ~c; } public void Update(byte[] buf, int off, int len) { UInt32 c = ~crc; while (--len >= 0) c = crcTable[(c ^ buf[off++]) & 0xff] ^ (c >> 8); crc = ~c; } public void Update(byte[] buf) { Update(buf, 0, buf.Length); } } public class TextSupport { /// /// Copies an array of chars obtained from a String into a specified array of chars /// /// The String to get the chars from /// Position of the String to start getting the chars /// Position of the String to end getting the chars /// Array to return the chars /// Position of the destination array of chars to start storing the chars /// An array of chars public static void GetCharsFromString(string sourceString, int sourceStart, int sourceEnd, char[] destinationArray, int destinationStart) { int sourceCounter; int destinationCounter; sourceCounter = sourceStart; destinationCounter = destinationStart; while (sourceCounter < sourceEnd) { destinationArray[destinationCounter] = (char)sourceString[sourceCounter]; sourceCounter++; destinationCounter++; } } } /// /// Support class used to handle threads /// public class ThreadClass : IThreadRunnable { /// /// The instance of System.Threading.Thread /// private System.Threading.Thread threadField; /// /// Initializes a new instance of the ThreadClass class /// public ThreadClass() { threadField = new System.Threading.Thread(new System.Threading.ThreadStart(Run)); } /// /// Initializes a new instance of the Thread class. /// /// The name of the thread public ThreadClass(System.String Name) { threadField = new System.Threading.Thread(new System.Threading.ThreadStart(Run)); this.Name = Name; } /// /// Initializes a new instance of the Thread class. /// /// A ThreadStart delegate that references the methods to be invoked when this thread begins executing public ThreadClass(System.Threading.ThreadStart Start) { threadField = new System.Threading.Thread(Start); } /// /// Initializes a new instance of the Thread class. /// /// A ThreadStart delegate that references the methods to be invoked when this thread begins executing /// The name of the thread public ThreadClass(System.Threading.ThreadStart Start, System.String Name) { threadField = new System.Threading.Thread(Start); this.Name = Name; } /// /// This method has no functionality unless the method is overridden /// public virtual void Run() { } /// /// Causes the operating system to change the state of the current thread instance to ThreadState.Running /// public virtual void Start() { threadField.Start(); } /// /// Interrupts a thread that is in the WaitSleepJoin thread state /// public virtual void Interrupt() { threadField.Interrupt(); } /// /// Gets the current thread instance /// public System.Threading.Thread Instance { get { return threadField; } set { threadField = value; } } /// /// Gets or sets the name of the thread /// public System.String Name { get { return threadField.Name; } set { if (threadField.Name == null) threadField.Name = value; } } public void SetDaemon(bool isDaemon) { threadField.IsBackground = isDaemon; } /// /// Gets or sets a value indicating the scheduling priority of a thread /// public System.Threading.ThreadPriority Priority { get { try { return threadField.Priority; } catch { return System.Threading.ThreadPriority.Normal; } } set { try { threadField.Priority = value; } catch{} } } /// /// Gets a value indicating the execution status of the current thread /// public bool IsAlive { get { return threadField.IsAlive; } } /// /// Gets or sets a value indicating whether or not a thread is a background thread. /// public bool IsBackground { get { return threadField.IsBackground; } set { threadField.IsBackground = value; } } /// /// Blocks the calling thread until a thread terminates /// public void Join() { threadField.Join(); } /// /// Blocks the calling thread until a thread terminates or the specified time elapses /// /// Time of wait in milliseconds public void Join(long MiliSeconds) { threadField.Join(new System.TimeSpan(MiliSeconds * 10000)); } /// /// Blocks the calling thread until a thread terminates or the specified time elapses /// /// Time of wait in milliseconds /// Time of wait in nanoseconds public void Join(long MiliSeconds, int NanoSeconds) { threadField.Join(new System.TimeSpan(MiliSeconds * 10000 + NanoSeconds * 100)); } /// /// Resumes a thread that has been suspended /// public void Resume() { System.Threading.Monitor.PulseAll(threadField); } /// /// Raises a ThreadAbortException in the thread on which it is invoked, /// to begin the process of terminating the thread. Calling this method /// usually terminates the thread /// public void Abort() { threadField.Abort(); } /// /// Raises a ThreadAbortException in the thread on which it is invoked, /// to begin the process of terminating the thread while also providing /// exception information about the thread termination. /// Calling this method usually terminates the thread. /// /// An object that contains application-specific information, such as state, which can be used by the thread being aborted public void Abort(object stateInfo) { threadField.Abort(stateInfo); } /// /// Suspends the thread, if the thread is already suspended it has no effect /// public void Suspend() { System.Threading.Monitor.Wait(threadField); } /// /// Obtain a String that represents the current object /// /// A String that represents the current object public override System.String ToString() { return "Thread[" + Name + "," + Priority.ToString() + "]"; } [ThreadStatic] static ThreadClass This = null; // named as the Java version public static ThreadClass CurrentThread() { return Current(); } public static void Sleep(long ms) { // casting long ms to int ms could lose resolution, however unlikely // that someone would want to sleep for that long... System.Threading.Thread.Sleep((int)ms); } /// /// Gets the currently running thread /// /// The currently running thread public static ThreadClass Current() { if (This == null) { This = new ThreadClass(); This.Instance = System.Threading.Thread.CurrentThread; } return This; } public static bool operator ==(ThreadClass t1, object t2) { if (((object)t1) == null) return t2 == null; return t1.Equals(t2); } public static bool operator !=(ThreadClass t1, object t2) { return !(t1 == t2); } public override bool Equals(object obj) { if (obj == null) return false; if (obj is ThreadClass) return this.threadField.Equals( ((ThreadClass)obj).threadField ); return false; } public override int GetHashCode() { return this.threadField.GetHashCode(); } } /// /// Represents the methods to support some operations over files. /// public class FileSupport { /// /// Returns an array of abstract pathnames representing the files and directories of the specified path. /// /// The abstract pathname to list it childs. /// An array of abstract pathnames childs of the path specified or null if the path is not a directory public static System.IO.FileInfo[] GetFiles(System.IO.FileInfo path) { if ((path.Attributes & System.IO.FileAttributes.Directory) > 0) { String[] fullpathnames = System.IO.Directory.GetFileSystemEntries(path.FullName); System.IO.FileInfo[] result = new System.IO.FileInfo[fullpathnames.Length]; for (int i = 0; i < result.Length ; i++) result[i] = new System.IO.FileInfo(fullpathnames[i]); return result; } else return null; } /// /// Returns a list of files in a give directory. /// /// The full path name to the directory. /// /// An array containing the files. public static System.String[] GetLuceneIndexFiles(System.String fullName, Lucene.Net.Index.IndexFileNameFilter indexFileNameFilter) { System.IO.DirectoryInfo dInfo = new System.IO.DirectoryInfo(fullName); System.Collections.ArrayList list = new System.Collections.ArrayList(); foreach (System.IO.FileInfo fInfo in dInfo.GetFiles()) { if (indexFileNameFilter.Accept(fInfo, fInfo.Name) == true) { list.Add(fInfo.Name); } } System.String[] retFiles = new System.String[list.Count]; list.CopyTo(retFiles); return retFiles; } // Disable the obsolete warning since we must use FileStream.Handle // because Mono does not support FileSystem.SafeFileHandle at present. #pragma warning disable 618 /// /// Flushes the specified file stream. Ensures that all buffered /// data is actually written to the file system. /// /// The file stream. public static void Sync(System.IO.FileStream fileStream) { if (fileStream == null) throw new ArgumentNullException("fileStream"); fileStream.Flush(); if (OS.IsWindows) { if (!FlushFileBuffers(fileStream.Handle)) throw new System.IO.IOException(); } else if (OS.IsUnix) { if (fsync(fileStream.Handle) != IntPtr.Zero) throw new System.IO.IOException(); } else { throw new NotImplementedException(); } } #pragma warning restore 618 [System.Runtime.InteropServices.DllImport("libc")] extern static IntPtr fsync(IntPtr fd); [System.Runtime.InteropServices.DllImport("kernel32.dll")] extern static bool FlushFileBuffers(IntPtr hFile); } /// /// A simple class for number conversions. /// public class Number { /// /// Min radix value. /// public const int MIN_RADIX = 2; /// /// Max radix value. /// public const int MAX_RADIX = 36; private const System.String digits = "0123456789abcdefghijklmnopqrstuvwxyz"; /// /// Converts a number to System.String. /// /// /// public static System.String ToString(long number) { System.Text.StringBuilder s = new System.Text.StringBuilder(); if (number == 0) { s.Append("0"); } else { if (number < 0) { s.Append("-"); number = -number; } while (number > 0) { char c = digits[(int)number % 36]; s.Insert(0, c); number = number / 36; } } return s.ToString(); } /// /// Converts a number to System.String. /// /// /// public static System.String ToString(float f) { if (((float)(int)f) == f) { return ((int)f).ToString() + ".0"; } else { return f.ToString(System.Globalization.NumberFormatInfo.InvariantInfo); } } /// /// Converts a number to System.String in the specified radix. /// /// A number to be converted. /// A radix. /// A System.String representation of the number in the specified redix. public static System.String ToString(long i, int radix) { if (radix < MIN_RADIX || radix > MAX_RADIX) radix = 10; char[] buf = new char[65]; int charPos = 64; bool negative = (i < 0); if (!negative) { i = -i; } while (i <= -radix) { buf[charPos--] = digits[(int)(-(i % radix))]; i = i / radix; } buf[charPos] = digits[(int)(-i)]; if (negative) { buf[--charPos] = '-'; } return new System.String(buf, charPos, (65 - charPos)); } /// /// Parses a number in the specified radix. /// /// An input System.String. /// A radix. /// The parsed number in the specified radix. public static long Parse(System.String s, int radix) { if (s == null) { throw new ArgumentException("null"); } if (radix < MIN_RADIX) { throw new NotSupportedException("radix " + radix + " less than Number.MIN_RADIX"); } if (radix > MAX_RADIX) { throw new NotSupportedException("radix " + radix + " greater than Number.MAX_RADIX"); } long result = 0; long mult = 1; s = s.ToLower(); for (int i = s.Length - 1; i >= 0; i--) { int weight = digits.IndexOf(s[i]); if (weight == -1) throw new FormatException("Invalid number for the specified radix"); result += (weight * mult); mult *= radix; } return result; } /// /// Performs an unsigned bitwise right shift with the specified number /// /// Number to operate on /// Ammount of bits to shift /// The resulting number from the shift operation public static int URShift(int number, int bits) { return (int) (((uint) number) >> bits); } /// /// Performs an unsigned bitwise right shift with the specified number /// /// Number to operate on /// Ammount of bits to shift /// The resulting number from the shift operation public static long URShift(long number, int bits) { return (long) (((ulong) number) >> bits); } /// /// Returns the index of the first bit that is set to true that occurs /// on or after the specified starting index. If no such bit exists /// then -1 is returned. /// /// The BitArray object. /// The index to start checking from (inclusive). /// The index of the next set bit. public static int NextSetBit(System.Collections.BitArray bits, int fromIndex) { for (int i = fromIndex; i < bits.Length; i++) { if (bits[i] == true) { return i; } } return -1; } /// /// Converts a System.String number to long. /// /// /// public static long ToInt64(System.String s) { long number = 0; int factor; // handle negative number if (s.StartsWith("-")) { s = s.Substring(1); factor = -1; } else { factor = 1; } // generate number for (int i = s.Length - 1; i > -1; i--) { int n = digits.IndexOf(s[i]); // not supporting fractional or scientific notations if (n < 0) throw new System.ArgumentException("Invalid or unsupported character in number: " + s[i]); number += (n * factor); factor *= 36; } return number; } } /// /// Mimics Java's Character class. /// public class Character { private const char charNull= '\0'; private const char charZero = '0'; private const char charA = 'a'; /// /// public static int MAX_RADIX { get { return 36; } } /// /// public static int MIN_RADIX { get { return 2; } } /// /// /// /// /// /// public static char ForDigit(int digit, int radix) { // if radix or digit is out of range, // return the null character. if (radix < Character.MIN_RADIX) return charNull; if (radix > Character.MAX_RADIX) return charNull; if (digit < 0) return charNull; if (digit >= radix) return charNull; // if digit is less than 10, // return '0' plus digit if (digit < 10) return (char) ( (int) charZero + digit); // otherwise, return 'a' plus digit. return (char) ((int) charA + digit - 10); } } /// /// /// public class Double { public static System.Double Parse(System.String s) { try { return System.Double.Parse(s.Replace(".", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator)); } catch (OverflowException) { return double.MaxValue; } } } /// /// /// public class Single { /// /// /// /// /// /// /// public static System.Single Parse(System.String s, System.Globalization.NumberStyles style, System.IFormatProvider provider) { try { if (s.EndsWith("f") || s.EndsWith("F")) return System.Single.Parse(s.Substring(0, s.Length - 1), style, provider); else return System.Single.Parse(s, style, provider); } catch (System.FormatException fex) { throw fex; } } /// /// /// /// /// /// public static System.Single Parse(System.String s, System.IFormatProvider provider) { try { if (s.EndsWith("f") || s.EndsWith("F")) return System.Single.Parse(s.Substring(0, s.Length - 1), provider); else return System.Single.Parse(s, provider); } catch (System.FormatException fex) { throw fex; } } /// /// /// /// /// /// public static System.Single Parse(System.String s, System.Globalization.NumberStyles style) { try { if (s.EndsWith("f") || s.EndsWith("F")) return System.Single.Parse(s.Substring(0, s.Length - 1), style); else return System.Single.Parse(s, style); } catch(System.FormatException fex) { throw fex; } } /// /// /// /// /// public static System.Single Parse(System.String s) { try { if (s.EndsWith("f") || s.EndsWith("F")) return System.Single.Parse(s.Substring(0, s.Length - 1).Replace(".", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator)); else return System.Single.Parse(s.Replace(".", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator)); } catch(System.FormatException fex) { throw fex; } } public static bool TryParse(System.String s, out float f) { bool ok = false; if (s.EndsWith("f") || s.EndsWith("F")) ok = System.Single.TryParse(s.Substring(0, s.Length - 1).Replace(".", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator), out f); else ok = System.Single.TryParse(s.Replace(".", System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator), out f); return ok; } /// /// /// /// /// public static string ToString(float f) { return f.ToString().Replace(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, "."); } /// /// /// /// /// /// public static string ToString(float f, string format) { return f.ToString(format).Replace(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator, "."); } } /// /// /// public class AppSettings { static System.Collections.Specialized.ListDictionary settings = new System.Collections.Specialized.ListDictionary(); /// /// /// /// /// public static void Set(System.String key, int defValue) { settings[key] = defValue; } /// /// /// /// /// public static void Set(System.String key, long defValue) { settings[key] = defValue; } /// /// /// /// /// public static void Set(System.String key, System.String defValue) { settings[key] = defValue; } /// /// /// /// /// public static void Set(System.String key, bool defValue) { settings[key] = defValue; } /// /// /// /// /// /// public static int Get(System.String key, int defValue) { if (settings[key] != null) { return (int) settings[key]; } System.String theValue = System.Configuration.ConfigurationManager.AppSettings.Get(key); if (theValue == null) { return defValue; } int retValue = System.Convert.ToInt32(theValue.Trim()); settings[key] = retValue; return retValue; } /// /// /// /// /// /// public static long Get(System.String key, long defValue) { if (settings[key] != null) { return (long) settings[key]; } System.String theValue = System.Configuration.ConfigurationManager.AppSettings.Get(key); if (theValue == null) { return defValue; } long retValue = System.Convert.ToInt64(theValue.Trim()); settings[key] = retValue; return retValue; } /// /// /// /// /// /// public static System.String Get(System.String key, System.String defValue) { if (settings[key] != null) { return (System.String) settings[key]; } System.String theValue = System.Configuration.ConfigurationManager.AppSettings.Get(key); if (theValue == null) { return defValue; } settings[key] = theValue; return theValue; } public static bool Get(System.String key, bool defValue) { if (settings[key] != null) { return (bool)settings[key]; } System.String theValue = System.Configuration.ConfigurationManager.AppSettings.Get(key); if (theValue == null) { return defValue; } bool retValue = System.Convert.ToBoolean(theValue.Trim()); settings[key] = retValue; return retValue; } } /// /// This class provides supporting methods of java.util.BitSet /// that are not present in System.Collections.BitArray. /// public class BitSetSupport { /// /// Returns the next set bit at or after index, or -1 if no such bit exists. /// /// /// the index of bit array at which to start checking /// the next set bit or -1 public static int NextSetBit(System.Collections.BitArray bitArray, int index) { while (index < bitArray.Length) { // if index bit is set, return it // otherwise check next index bit if (bitArray.Get(index)) return index; else index++; } // if no bits are set at or after index, return -1 return -1; } /// /// Returns the next un-set bit at or after index, or -1 if no such bit exists. /// /// /// the index of bit array at which to start checking /// the next set bit or -1 public static int NextClearBit(System.Collections.BitArray bitArray, int index) { while (index < bitArray.Length) { // if index bit is not set, return it // otherwise check next index bit if (!bitArray.Get(index)) return index; else index++; } // if no bits are set at or after index, return -1 return -1; } /// /// Returns the number of bits set to true in this BitSet. /// /// The BitArray object. /// The number of bits set to true in this BitSet. public static int Cardinality(System.Collections.BitArray bits) { int count = 0; for (int i = 0; i < bits.Count; i++) { if (bits[i]) count++; } return count; } } /// /// Summary description for TestSupportClass. /// public class Compare { /// /// Compares two Term arrays for equality. /// /// First Term array to compare /// Second Term array to compare /// true if the Terms are equal in both arrays, false otherwise public static bool CompareTermArrays(Lucene.Net.Index.Term[] t1, Lucene.Net.Index.Term[] t2) { if (t1.Length != t2.Length) return false; for (int i = 0; i < t1.Length; i++) { if (t1[i].CompareTo(t2[i]) == 0) { return true; } } return false; } } #region WEAKHASHTABLE /// /// A Hashtable which holds weak references to its keys so they /// can be collected during GC. /// [System.Diagnostics.DebuggerDisplay("Count = {Values.Count}")] public class WeakHashTable : Hashtable, IEnumerable { /// /// A weak referene wrapper for the hashtable keys. Whenever a key\value pair /// is added to the hashtable, the key is wrapped using a WeakKey. WeakKey saves the /// value of the original object hashcode for fast comparison. /// class WeakKey { WeakReference reference; int hashCode; public WeakKey(object key) { if (key == null) throw new ArgumentNullException("key"); hashCode = key.GetHashCode(); reference = new WeakReference(key); } public override int GetHashCode() { return hashCode; } public object Target { get { return reference.Target; } } public bool IsAlive { get { return reference.IsAlive; } } } /// /// A Dictionary enumerator which wraps the original hashtable enumerator /// and performs 2 tasks: Extract the real key from a WeakKey and skip keys /// that were already collected. /// class WeakDictionaryEnumerator : IDictionaryEnumerator { IDictionaryEnumerator baseEnumerator; object currentKey; object currentValue; public WeakDictionaryEnumerator(IDictionaryEnumerator baseEnumerator) { this.baseEnumerator = baseEnumerator; } public DictionaryEntry Entry { get { return new DictionaryEntry(this.currentKey, this.currentValue); } } public object Key { get { return this.currentKey; } } public object Value { get { return this.currentValue; } } public object Current { get { return Entry; } } public bool MoveNext() { while (baseEnumerator.MoveNext()) { object key = ((WeakKey)baseEnumerator.Key).Target; if (key != null) { this.currentKey = key; this.currentValue = baseEnumerator.Value; return true; } } return false; } public void Reset() { baseEnumerator.Reset(); this.currentKey = null; this.currentValue = null; } } /// /// Serves as a simple "GC Monitor" that indicates whether cleanup is needed. /// If collectableObject.IsAlive is false, GC has occurred and we should perform cleanup /// WeakReference collectableObject = new WeakReference(new Object()); /// /// Customize the hashtable lookup process by overriding KeyEquals. KeyEquals /// will compare both WeakKey to WeakKey and WeakKey to real keys /// protected override bool KeyEquals(object x, object y) { if (x == y) return true; if (x is WeakKey) { x = ((WeakKey)x).Target; if (x == null) return false; } if (y is WeakKey) { y = ((WeakKey)y).Target; if (y == null) return false; } return x.Equals(y); } protected override int GetHash(object key) { return key.GetHashCode(); } /// /// Perform cleanup if GC occurred /// private void CleanIfNeeded() { if (collectableObject.Target == null) { Clean(); collectableObject = new WeakReference(new Object()); } } /// /// Iterate over all keys and remove keys that were collected /// private void Clean() { foreach (WeakKey wtk in ((Hashtable)base.Clone()).Keys) { if (!wtk.IsAlive) { Remove(wtk); } } } /// /// Wrap each key with a WeakKey and add it to the hashtable /// public override void Add(object key, object value) { CleanIfNeeded(); base.Add(new WeakKey(key), value); } public override IDictionaryEnumerator GetEnumerator() { Hashtable tmp = null; tmp = (Hashtable)base.Clone(); return new WeakDictionaryEnumerator(tmp.GetEnumerator()); } /// /// Create a temporary copy of the real keys and return that /// public override ICollection Keys { get { ArrayList keys = new ArrayList(Count); Hashtable tmpTable = (Hashtable)base.Clone(); foreach (WeakKey key in tmpTable.Keys) { object realKey = key.Target; if (realKey != null) keys.Add(realKey); } return keys; } } public override object this[object key] { get { return base[key]; } set { CleanIfNeeded(); base[new WeakKey(key)] = value; } } public override void CopyTo(Array array, int index) { int arrayIndex = index; foreach (DictionaryEntry de in this) { array.SetValue(de, arrayIndex++); } } public override int Count { get { CleanIfNeeded(); return base.Count; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } #endregion public class Cryptography { static public bool FIPSCompliant = false; static public System.Security.Cryptography.HashAlgorithm GetHashAlgorithm() { if (FIPSCompliant) { //LUCENENET-175 //No Assumptions should be made on the HashAlgorithm. It may change in time. //SHA256 SHA384 SHA512 etc. return System.Security.Cryptography.SHA1.Create(); } return System.Security.Cryptography.MD5.Create(); } } /// /// Support class used to handle Hashtable addition, which does a check /// first to make sure the added item is unique in the hash. /// public class CollectionsHelper { public static void Add(System.Collections.Hashtable hashtable, System.Object item) { hashtable.Add(item, item); } public static void AddIfNotContains(System.Collections.Hashtable hashtable, System.Object item) { if (hashtable.Contains(item) == false) { hashtable.Add(item, item); } } public static void AddIfNotContains(System.Collections.ArrayList hashtable, System.Object item) { if (hashtable.Contains(item) == false) { hashtable.Add(item); } } public static void AddAll(System.Collections.Hashtable hashtable, System.Collections.ICollection items) { System.Collections.IEnumerator iter = items.GetEnumerator(); System.Object item; while (iter.MoveNext()) { item = iter.Current; hashtable.Add(item, item); } } public static void AddAllIfNotContains(System.Collections.Hashtable hashtable, System.Collections.IList items) { System.Object item; for (int i = 0; i < items.Count; i++) { item = items[i]; if (hashtable.Contains(item) == false) { hashtable.Add(item, item); } } } public static void AddAllIfNotContains(System.Collections.Hashtable hashtable, System.Collections.ICollection items) { System.Collections.IEnumerator iter = items.GetEnumerator(); System.Object item; while (iter.MoveNext()) { item = iter.Current; if (hashtable.Contains(item) == false) { hashtable.Add(item, item); } } } public static void AddAllIfNotContains(System.Collections.Generic.IDictionary hashtable, System.Collections.Generic.ICollection items) { foreach (string s in items) { if (hashtable.ContainsKey(s) == false) { hashtable.Add(s, s); } } } public static void AddAll(System.Collections.Generic.IDictionary hashtable, System.Collections.Generic.ICollection items) { foreach (string s in items) { hashtable.Add(s, s); } } public static bool Contains(System.Collections.Generic.ICollection col, string item) { foreach (string s in col) if (s == item) return true; return false; } public static bool Contains(System.Collections.ICollection col, System.Object item) { System.Collections.IEnumerator iter = col.GetEnumerator(); while (iter.MoveNext()) { if (iter.Current.Equals(item)) return true; } return false; } public static System.String CollectionToString(System.Collections.Generic.IDictionary c) { Hashtable t = new Hashtable(); foreach (string key in c.Keys) { t.Add(key, c[key]); } return CollectionToString(t); } /// /// Converts the specified collection to its string representation. /// /// The collection to convert to string. /// A string representation of the specified collection. public static System.String CollectionToString(System.Collections.ICollection c) { System.Text.StringBuilder s = new System.Text.StringBuilder(); if (c != null) { System.Collections.ArrayList l = new System.Collections.ArrayList(c); bool isDictionary = (c is System.Collections.BitArray || c is System.Collections.Hashtable || c is System.Collections.IDictionary || c is System.Collections.Specialized.NameValueCollection || (l.Count > 0 && l[0] is System.Collections.DictionaryEntry)); for (int index = 0; index < l.Count; index++) { if (l[index] == null) s.Append("null"); else if (!isDictionary) s.Append(l[index]); else { isDictionary = true; if (c is System.Collections.Specialized.NameValueCollection) s.Append(((System.Collections.Specialized.NameValueCollection)c).GetKey(index)); else s.Append(((System.Collections.DictionaryEntry)l[index]).Key); s.Append("="); if (c is System.Collections.Specialized.NameValueCollection) s.Append(((System.Collections.Specialized.NameValueCollection)c).GetValues(index)[0]); else s.Append(((System.Collections.DictionaryEntry)l[index]).Value); } if (index < l.Count - 1) s.Append(", "); } if (isDictionary) { if (c is System.Collections.ArrayList) isDictionary = false; } if (isDictionary) { s.Insert(0, "{"); s.Append("}"); } else { s.Insert(0, "["); s.Append("]"); } } else s.Insert(0, "null"); return s.ToString(); } /// /// Compares two string arrays for equality. /// /// First string array list to compare /// Second string array list to compare /// true if the strings are equal in both arrays, false otherwise public static bool CompareStringArrays(System.String[] l1, System.String[] l2) { if (l1.Length != l2.Length) return false; for (int i = 0; i < l1.Length; i++) { if (l1[i] != l2[i]) return false; } return true; } /// /// Sorts an IList collections /// /// The System.Collections.IList instance that will be sorted /// The Comparator criteria, null to use natural comparator. public static void Sort(System.Collections.IList list, System.Collections.IComparer Comparator) { if (((System.Collections.ArrayList)list).IsReadOnly) throw new System.NotSupportedException(); if ((Comparator == null) || (Comparator is System.Collections.Comparer)) { try { ((System.Collections.ArrayList)list).Sort(); } catch (System.InvalidOperationException e) { throw new System.InvalidCastException(e.Message); } } else { try { ((System.Collections.ArrayList)list).Sort(Comparator); } catch (System.InvalidOperationException e) { throw new System.InvalidCastException(e.Message); } } } /// /// Fills the array with an specific value from an specific index to an specific index. /// /// The array to be filled. /// The first index to be filled. /// The last index to be filled. /// The value to fill the array with. public static void Fill(System.Array array, System.Int32 fromindex, System.Int32 toindex, System.Object val) { System.Object Temp_Object = val; System.Type elementtype = array.GetType().GetElementType(); if (elementtype != val.GetType()) Temp_Object = System.Convert.ChangeType(val, elementtype); if (array.Length == 0) throw (new System.NullReferenceException()); if (fromindex > toindex) throw (new System.ArgumentException()); if ((fromindex < 0) || ((System.Array)array).Length < toindex) throw (new System.IndexOutOfRangeException()); for (int index = (fromindex > 0) ? fromindex-- : fromindex; index < toindex; index++) array.SetValue(Temp_Object, index); } /// /// Fills the array with an specific value. /// /// The array to be filled. /// The value to fill the array with. public static void Fill(System.Array array, System.Object val) { Fill(array, 0, array.Length, val); } /// /// Compares the entire members of one array whith the other one. /// /// The array to be compared. /// The array to be compared with. /// Returns true if the two specified arrays of Objects are equal /// to one another. The two arrays are considered equal if both arrays /// contain the same number of elements, and all corresponding pairs of /// elements in the two arrays are equal. Two objects e1 and e2 are /// considered equal if (e1==null ? e2==null : e1.equals(e2)). In other /// words, the two arrays are equal if they contain the same elements in /// the same order. Also, two array references are considered equal if /// both are null. public static bool Equals(System.Array array1, System.Array array2) { bool result = false; if ((array1 == null) && (array2 == null)) result = true; else if ((array1 != null) && (array2 != null)) { if (array1.Length == array2.Length) { int length = array1.Length; result = true; for (int index = 0; index < length; index++) { System.Object o1 = array1.GetValue(index); System.Object o2 = array2.GetValue(index); if (o1 == null && o2 == null) continue; // they match else if (o1 == null || !o1.Equals(o2)) { result = false; break; } } } } return result; } } /// A collection of which can be /// looked up by instances of . /// The type of the items contains in this /// collection. /// The type of the keys that can be used to look /// up the items. internal class GeneralKeyedCollection : System.Collections.ObjectModel.KeyedCollection { /// Creates a new instance of the /// class. /// The which will convert /// instances of to /// when the override of is called. internal GeneralKeyedCollection(Converter converter) : base() { // If the converter is null, throw an exception. if (converter == null) throw new ArgumentNullException("converter"); // Store the converter. this.converter = converter; // That's all folks. return; } /// The which will convert /// instances of to /// when the override of is called. private readonly Converter converter; /// Converts an item that is added to the collection to /// a key. /// The instance of /// to convert into an instance of . /// The instance of which is the /// key for this item. protected override TKey GetKeyForItem(TItem item) { // The converter is not null. System.Diagnostics.Debug.Assert(converter != null); // Call the converter. return converter(item); } /// Determines if a key for an item exists in this /// collection. /// The instance of /// to see if it exists in this collection. /// True if the key exists in the collection, false otherwise. public bool ContainsKey(TKey key) { // Call the dictionary - it is lazily created when the first item is added if (Dictionary != null) { return Dictionary.ContainsKey(key); } else { return false; } } } /// Represents a strongly typed list of objects that can be accessed by index. /// Provides methods to search, sort, and manipulate lists. Also provides functionality /// to compare lists against each other through an implementations of /// . /// The type of elements in the list. [Serializable] public class EquatableList : System.Collections.Generic.List, IEquatable>, ICloneable { /// Initializes a new instance of the /// class that is empty and has the /// default initial capacity. public EquatableList() : base() { } /// Initializes a new instance of the /// class that contains elements copied from the specified collection and has /// sufficient capacity to accommodate the number of elements copied. /// The collection whose elements are copied to the new list. public EquatableList(System.Collections.Generic.IEnumerable collection) : base(collection) { } /// Initializes a new instance of the /// class that is empty and has the specified initial capacity. /// The number of elements that the new list can initially store. public EquatableList(int capacity) : base(capacity) { } /// Adds a range of objects represented by the /// implementation. /// The /// implementation to add to this list. public void AddRange(ICollection c) { // If the collection is null, throw an exception. if (c == null) throw new ArgumentNullException("c"); // Pre-compute capacity. Capacity = Math.Max(c.Count + Count, Capacity); // Cycle through the items and add. foreach (T item in c) { // Add the item. Add(item); } } /// Compares the counts of two /// implementations. /// This uses a trick in LINQ, sniffing types for implementations /// of interfaces that might supply shortcuts when trying to make comparisons. /// In this case, that is the and /// interfaces, either of which can provide a count /// which can be used in determining the equality of sequences (if they don't have /// the same count, then they can't be equal). /// The from the left hand side of the /// comparison to check the count of. /// The from the right hand side of the /// comparison to check the count of. /// Null if the result is indeterminate. This occurs when either /// or doesn't implement or . /// Otherwise, it will get the count from each and return true if they are equal, false otherwise. private static bool? EnumerableCountsEqual(System.Collections.Generic.IEnumerable x, System.Collections.Generic.IEnumerable y) { // Get the ICollection and ICollection interfaces. System.Collections.Generic.ICollection xOfTCollection = x as System.Collections.Generic.ICollection; System.Collections.Generic.ICollection yOfTCollection = y as System.Collections.Generic.ICollection; ICollection xCollection = x as ICollection; ICollection yCollection = y as ICollection; // The count in x and y. int? xCount = xOfTCollection != null ? xOfTCollection.Count : xCollection != null ? xCollection.Count : (int?)null; int? yCount = yOfTCollection != null ? yOfTCollection.Count : yCollection != null ? yCollection.Count : (int?)null; // If either are null, return null, the result is indeterminate. if (xCount == null || yCount == null) { // Return null, indeterminate. return null; } // Both counts are non-null, compare. return xCount == yCount; } /// Compares the contents of a /// implementation to another one to determine equality. /// Thinking of the implementation as /// a string with any number of characters, the algorithm checks /// each item in each list. If any item of the list is not equal (or /// one list contains all the elements of another list), then that list /// element is compared to the other list element to see which /// list is greater. /// The implementation /// that is considered the left hand side. /// The implementation /// that is considered the right hand side. /// True if the items are equal, false otherwise. private static bool Equals(System.Collections.Generic.IEnumerable x, System.Collections.Generic.IEnumerable y) { // If x and y are null, then return true, they are the same. if (x == null && y == null) { // They are the same, return 0. return true; } // If one is null, then return a value based on whether or not // one is null or not. if (x == null || y == null) { // Return false, one is null, the other is not. return false; } // Check to see if the counts on the IEnumerable implementations are equal. // This is a shortcut, if they are not equal, then the lists are not equal. // If the result is indeterminate, then get out. bool? enumerableCountsEqual = EnumerableCountsEqual(x, y); // If the enumerable counts have been able to be calculated (indicated by // a non-null value) and it is false, then no need to iterate through the items. if (enumerableCountsEqual != null && !enumerableCountsEqual.Value) { // The sequences are not equal. return false; } // The counts of the items in the enumerations are equal, or indeterminate // so a full iteration needs to be made to compare each item. // Get the default comparer for T first. System.Collections.Generic.EqualityComparer defaultComparer = System.Collections.Generic.EqualityComparer.Default; // Get the enumerator for y. System.Collections.Generic.IEnumerator otherEnumerator = y.GetEnumerator(); // Call Dispose on IDisposable if there is an implementation on the // IEnumerator returned by a call to y.GetEnumerator(). using (otherEnumerator as IDisposable) { // Cycle through the items in this list. foreach (T item in x) { // If there isn't an item to get, then this has more // items than that, they are not equal. if (!otherEnumerator.MoveNext()) { // Return false. return false; } // Perform a comparison. Must check this on the left hand side // and that on the right hand side. bool comparison = defaultComparer.Equals(item, otherEnumerator.Current); // If the value is false, return false. if (!comparison) { // Return the value. return comparison; } } // If there are no more items, then return true, the sequences // are equal. if (!otherEnumerator.MoveNext()) { // The sequences are equal. return true; } // The other sequence has more items than this one, return // false, these are not equal. return false; } } #region IEquatable> Members /// Compares this sequence to another /// implementation, returning true if they are equal, false otherwise. /// The other implementation /// to compare against. /// True if the sequence in /// is the same as this one. public bool Equals(System.Collections.Generic.IEnumerable other) { // Compare to the other sequence. If 0, then equal. return Equals(this, other); } #endregion /// Compares this object for equality against other. /// The other object to compare this object against. /// True if this object and are equal, false /// otherwise. public override bool Equals(object obj) { // Call the strongly typed version. return Equals(obj as System.Collections.Generic.IEnumerable); } /// Gets the hash code for the list. /// The hash code value. public override int GetHashCode() { // Call the static method, passing this. return GetHashCode(this); } /// Gets the hash code for the list. /// The /// implementation which will have all the contents hashed. /// The hash code value. public static int GetHashCode(System.Collections.Generic.IEnumerable source) { // If source is null, then return 0. if (source == null) return 0; // Seed the hash code with the hash code of the type. // This is done so that you don't have a lot of collisions of empty // ComparableList instances when placed in dictionaries // and things that rely on hashcodes. int hashCode = typeof(T).GetHashCode(); // Iterate through the items in this implementation. foreach (T item in source) { // Adjust the hash code. hashCode = 31 * hashCode + (item == null ? 0 : item.GetHashCode()); } // Return the hash code. return hashCode; } // TODO: When diverging from Java version of Lucene, can uncomment these to adhere to best practices when overriding the Equals method and implementing IEquatable. ///// Overload of the == operator, it compares a ///// to an ///// implementation. ///// The to compare ///// against . ///// The to compare ///// against . ///// True if the instances are equal, false otherwise. //public static bool operator ==(EquatableList x, System.Collections.Generic.IEnumerable y) //{ // // Call Equals. // return Equals(x, y); //} ///// Overload of the == operator, it compares a ///// to an ///// implementation. ///// The to compare ///// against . ///// The to compare ///// against . ///// True if the instances are equal, false otherwise. //public static bool operator ==(System.Collections.Generic.IEnumerable x, EquatableList y) //{ // // Call equals. // return Equals(x, y); //} ///// Overload of the != operator, it compares a ///// to an ///// implementation. ///// The to compare ///// against . ///// The to compare ///// against . ///// True if the instances are not equal, false otherwise. //public static bool operator !=(EquatableList x, System.Collections.Generic.IEnumerable y) //{ // // Return the negative of the equals operation. // return !(x == y); //} ///// Overload of the != operator, it compares a ///// to an ///// implementation. ///// The to compare ///// against . ///// The to compare ///// against . ///// True if the instances are not equal, false otherwise. //public static bool operator !=(System.Collections.Generic.IEnumerable x, EquatableList y) //{ // // Return the negative of the equals operation. // return !(x == y); //} #region ICloneable Members /// Clones the . /// This is a shallow clone. /// A new shallow clone of this /// . public object Clone() { // Just create a new one, passing this to the constructor. return new EquatableList(this); } #endregion } /// /// A simple wrapper to allow for the use of the GeneralKeyedCollection. The /// wrapper is required as there can be several keys for an object depending /// on how many interfaces it implements. /// internal sealed class AttributeImplItem { internal AttributeImplItem(Type key, Lucene.Net.Util.AttributeImpl value) { this.Key = key; this.Value = value; } internal Type Key; internal Lucene.Net.Util.AttributeImpl Value; } /// /// Provides platform infos. /// public class OS { static bool isUnix; static bool isWindows; static OS() { PlatformID pid = Environment.OSVersion.Platform; isWindows = pid == PlatformID.Win32NT || pid == PlatformID.Win32Windows; // we use integers instead of enum tags because "MacOS" // requires 2.0 SP2, 3.0 SP2 or 3.5 SP1. // 128 is mono's old platform tag for Unix. int id = (int)pid; isUnix = id == 4 || id == 6 || id == 128; } /// /// Whether we run under a Unix platform. /// public static bool IsUnix { get { return isUnix; } } /// /// Whether we run under a supported Windows platform. /// public static bool IsWindows { get { return isWindows; } } } public class SharpZipLib { static System.Reflection.Assembly asm = null; static SharpZipLib() { try { asm = System.Reflection.Assembly.Load("ICSharpCode.SharpZipLib"); } catch{} } public static Deflater CreateDeflater() { if (asm == null) throw new System.IO.FileNotFoundException("Can not load ICSharpCode.SharpZipLib.dll"); return new Deflater(asm.CreateInstance("ICSharpCode.SharpZipLib.Zip.Compression.Deflater")); } public static Inflater CreateInflater() { if (asm == null) throw new System.IO.FileNotFoundException("Can not load ICSharpCode.SharpZipLib.dll"); return new Inflater(asm.CreateInstance("ICSharpCode.SharpZipLib.Zip.Compression.Inflater")); } public class Inflater { delegate void SetInputDelegate(byte[] buffer); delegate bool GetIsFinishedDelegate(); delegate int InflateDelegate(byte[] buffer); SetInputDelegate setInputMethod; GetIsFinishedDelegate getIsFinishedMethod; InflateDelegate inflateMethod; internal Inflater(object inflaterInstance) { Type type = inflaterInstance.GetType(); setInputMethod = (SetInputDelegate)Delegate.CreateDelegate( typeof(SetInputDelegate), inflaterInstance, type.GetMethod("SetInput", new Type[] { typeof(byte[]) })); getIsFinishedMethod = (GetIsFinishedDelegate)Delegate.CreateDelegate( typeof(GetIsFinishedDelegate), inflaterInstance, type.GetMethod("get_IsFinished", Type.EmptyTypes)); inflateMethod = (InflateDelegate)Delegate.CreateDelegate( typeof(InflateDelegate), inflaterInstance, type.GetMethod("Inflate", new Type[] { typeof(byte[]) })); } public void SetInput(byte[] buffer) { setInputMethod(buffer); } public bool IsFinished { get { return getIsFinishedMethod(); } } public int Inflate(byte[] buffer) { return inflateMethod(buffer); } } public class Deflater { delegate void SetLevelDelegate(int level); delegate void SetInputDelegate(byte[] input, int offset, int count); delegate void FinishDelegate(); delegate bool GetIsFinishedDelegate(); delegate int DeflateDelegate(byte[] output); SetLevelDelegate setLevelMethod; SetInputDelegate setInputMethod; FinishDelegate finishMethod; GetIsFinishedDelegate getIsFinishedMethod; DeflateDelegate deflateMethod; public const int BEST_COMPRESSION = 9; internal Deflater(object deflaterInstance) { Type type = deflaterInstance.GetType(); setLevelMethod = (SetLevelDelegate)Delegate.CreateDelegate( typeof(SetLevelDelegate), deflaterInstance, type.GetMethod("SetLevel", new Type[] { typeof(int) })); setInputMethod = (SetInputDelegate)Delegate.CreateDelegate( typeof(SetInputDelegate), deflaterInstance, type.GetMethod("SetInput", new Type[] { typeof(byte[]), typeof(int), typeof(int) })); finishMethod = (FinishDelegate)Delegate.CreateDelegate( typeof(FinishDelegate), deflaterInstance, type.GetMethod("Finish", Type.EmptyTypes)); getIsFinishedMethod = (GetIsFinishedDelegate)Delegate.CreateDelegate( typeof(GetIsFinishedDelegate), deflaterInstance, type.GetMethod("get_IsFinished", Type.EmptyTypes)); deflateMethod = (DeflateDelegate)Delegate.CreateDelegate( typeof(DeflateDelegate), deflaterInstance, type.GetMethod("Deflate", new Type[] { typeof(byte[]) })); } public void SetLevel(int level) { setLevelMethod(level); } public void SetInput(byte[] input, int offset, int count) { setInputMethod(input, offset, count); } public void Finish() { finishMethod(); } public bool IsFinished { get { return getIsFinishedMethod(); } } public int Deflate(byte[] output) { return deflateMethod(output); } } } public class BuildType { #if DEBUG public static bool Debug = true; #else public static bool Debug = false; #endif } }