3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 /*============================================================
8 ** <OWNER>[....]</OWNER>
10 ** Class: FastResourceComparer
13 ** Purpose: A collection of quick methods for comparing
14 ** resource keys (strings)
17 ===========================================================*/
18 namespace System.Resources {
20 using System.Collections;
21 using System.Collections.Generic;
22 using System.Diagnostics.Contracts;
24 internal sealed class FastResourceComparer : IComparer, IEqualityComparer, IComparer<String>, IEqualityComparer<String>
26 internal static readonly FastResourceComparer Default = new FastResourceComparer();
28 // Implements IHashCodeProvider too, due to Hashtable requirements.
29 public int GetHashCode(Object key)
31 String s = (String) key;
32 return FastResourceComparer.HashFunction(s);
35 public int GetHashCode(String key)
37 return FastResourceComparer.HashFunction(key);
40 // This hash function MUST be publically documented with the resource
41 // file format, AND we may NEVER change this hash function's return
42 // value (without changing the file format).
43 internal static int HashFunction(String key)
45 // Never change this hash function. We must standardize it so that
46 // others can read & write our .resources files. Additionally, we
47 // have a copy of it in InternalResGen as well.
49 for(int i=0; i<key.Length; i++)
50 hash = ((hash << 5) + hash) ^ key[i];
54 // Compares Strings quickly in a case-sensitive way
55 public int Compare(Object a, Object b)
58 String sa = (String)a;
59 String sb = (String)b;
60 return String.CompareOrdinal(sa, sb);
63 public int Compare(String a, String b)
65 return String.CompareOrdinal(a, b);
68 public bool Equals(String a, String b)
70 return String.Equals(a, b);
73 public new bool Equals(Object a, Object b)
75 if (a == b) return true;
76 String sa = (String)a;
77 String sb = (String)b;
78 return String.Equals(sa,sb);
81 // Input is one string to compare with, and a byte[] containing chars in
82 // little endian unicode. Pass in the number of valid chars.
83 [System.Security.SecurityCritical] // auto-generated
84 public unsafe static int CompareOrdinal(String a, byte[] bytes, int bCharLength)
86 Contract.Assert(a != null && bytes != null, "FastResourceComparer::CompareOrdinal must have non-null params");
87 Contract.Assert(bCharLength * 2 <= bytes.Length, "FastResourceComparer::CompareOrdinal - numChars is too big!");
88 // This is a managed version of strcmp, but I can't take advantage
89 // of a terminating 0, unlike strcmp in C.
92 // Compare the min length # of characters, then return length diffs.
93 int numChars = a.Length;
94 if (numChars > bCharLength)
95 numChars = bCharLength;
96 if (bCharLength == 0) // Can't use fixed on a 0-element array.
97 return (a.Length == 0) ? 0 : -1;
98 fixed(byte* pb = bytes) {
101 while (i < numChars && r == 0) {
102 // little endian format
103 int b = pChar[0] | pChar[1] << 8;
105 pChar += sizeof(char);
108 if (r != 0) return r;
109 return a.Length - bCharLength;
112 [System.Security.SecurityCritical] // auto-generated
113 public static int CompareOrdinal(byte[] bytes, int aCharLength, String b)
115 return -CompareOrdinal(b, bytes, aCharLength);
118 // This method is to handle potentially misaligned data accesses.
119 // The byte* must point to little endian Unicode characters.
120 [System.Security.SecurityCritical] // auto-generated
121 internal unsafe static int CompareOrdinal(byte* a, int byteLen, String b)
123 Contract.Assert((byteLen & 1) == 0, "CompareOrdinal is expecting a UTF-16 string length, which must be even!");
124 Contract.Assert(a != null && b != null, "Null args not allowed.");
125 Contract.Assert(byteLen >= 0, "byteLen must be non-negative.");
129 // Compare the min length # of characters, then return length diffs.
130 int numChars = byteLen >> 1;
131 if (numChars > b.Length)
133 while(i < numChars && r == 0) {
134 // Must compare character by character, not byte by byte.
135 char aCh = (char) (*a++ | (*a++ << 8));
138 if (r != 0) return r;
139 return byteLen - b.Length * 2;