summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Resources/__FastResourceComparer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Resources/__FastResourceComparer.cs')
-rw-r--r--src/mscorlib/src/System/Resources/__FastResourceComparer.cs141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Resources/__FastResourceComparer.cs b/src/mscorlib/src/System/Resources/__FastResourceComparer.cs
new file mode 100644
index 0000000000..5bc7333863
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/__FastResourceComparer.cs
@@ -0,0 +1,141 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: A collection of quick methods for comparing
+** resource keys (strings)
+**
+**
+===========================================================*/
+namespace System.Resources {
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+
+ internal sealed class FastResourceComparer : IComparer, IEqualityComparer, IComparer<String>, IEqualityComparer<String>
+ {
+ internal static readonly FastResourceComparer Default = new FastResourceComparer();
+
+ // Implements IHashCodeProvider too, due to Hashtable requirements.
+ public int GetHashCode(Object key)
+ {
+ String s = (String) key;
+ return FastResourceComparer.HashFunction(s);
+ }
+
+ public int GetHashCode(String key)
+ {
+ return FastResourceComparer.HashFunction(key);
+ }
+
+ // This hash function MUST be publically documented with the resource
+ // file format, AND we may NEVER change this hash function's return
+ // value (without changing the file format).
+ internal static int HashFunction(String key)
+ {
+ // Never change this hash function. We must standardize it so that
+ // others can read & write our .resources files. Additionally, we
+ // have a copy of it in InternalResGen as well.
+ uint hash = 5381;
+ for(int i=0; i<key.Length; i++)
+ hash = ((hash << 5) + hash) ^ key[i];
+ return (int) hash;
+ }
+
+ // Compares Strings quickly in a case-sensitive way
+ public int Compare(Object a, Object b)
+ {
+ if (a == b) return 0;
+ String sa = (String)a;
+ String sb = (String)b;
+ return String.CompareOrdinal(sa, sb);
+ }
+
+ public int Compare(String a, String b)
+ {
+ return String.CompareOrdinal(a, b);
+ }
+
+ public bool Equals(String a, String b)
+ {
+ return String.Equals(a, b);
+ }
+
+ public new bool Equals(Object a, Object b)
+ {
+ if (a == b) return true;
+ String sa = (String)a;
+ String sb = (String)b;
+ return String.Equals(sa,sb);
+ }
+
+ // Input is one string to compare with, and a byte[] containing chars in
+ // little endian unicode. Pass in the number of valid chars.
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe static int CompareOrdinal(String a, byte[] bytes, int bCharLength)
+ {
+ Contract.Assert(a != null && bytes != null, "FastResourceComparer::CompareOrdinal must have non-null params");
+ Contract.Assert(bCharLength * 2 <= bytes.Length, "FastResourceComparer::CompareOrdinal - numChars is too big!");
+ // This is a managed version of strcmp, but I can't take advantage
+ // of a terminating 0, unlike strcmp in C.
+ int i = 0;
+ int r = 0;
+ // Compare the min length # of characters, then return length diffs.
+ int numChars = a.Length;
+ if (numChars > bCharLength)
+ numChars = bCharLength;
+ if (bCharLength == 0) // Can't use fixed on a 0-element array.
+ return (a.Length == 0) ? 0 : -1;
+ fixed(byte* pb = bytes) {
+
+ byte *pChar = pb;
+ while (i < numChars && r == 0) {
+ // little endian format
+ int b = pChar[0] | pChar[1] << 8;
+ r = a[i++] - b;
+ pChar += sizeof(char);
+ }
+ }
+ if (r != 0) return r;
+ return a.Length - bCharLength;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public static int CompareOrdinal(byte[] bytes, int aCharLength, String b)
+ {
+ return -CompareOrdinal(b, bytes, aCharLength);
+ }
+
+ // This method is to handle potentially misaligned data accesses.
+ // The byte* must point to little endian Unicode characters.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static int CompareOrdinal(byte* a, int byteLen, String b)
+ {
+ Contract.Assert((byteLen & 1) == 0, "CompareOrdinal is expecting a UTF-16 string length, which must be even!");
+ Contract.Assert(a != null && b != null, "Null args not allowed.");
+ Contract.Assert(byteLen >= 0, "byteLen must be non-negative.");
+
+ int r = 0;
+ int i = 0;
+ // Compare the min length # of characters, then return length diffs.
+ int numChars = byteLen >> 1;
+ if (numChars > b.Length)
+ numChars = b.Length;
+ while(i < numChars && r == 0) {
+ // Must compare character by character, not byte by byte.
+ char aCh = (char) (*a++ | (*a++ << 8));
+ r = aCh - b[i++];
+ }
+ if (r != 0) return r;
+ return byteLen - b.Length * 2;
+ }
+ }
+}
+