//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // // [....] //------------------------------------------------------------------------------ namespace System.Xml { using System.Collections; using System.Diagnostics; #if !SILVERLIGHT using Microsoft.Win32; using System.Reflection; using System.Security; using System.Security.Permissions; #endif /// /// /// [To be supplied.] /// #if !SILVERLIGHT [Serializable] #endif public class XmlQualifiedName { #if !SILVERLIGHT delegate int HashCodeOfStringDelegate(string s, int sLen, long additionalEntropy); static HashCodeOfStringDelegate hashCodeDelegate = null; #endif string name; string ns; #if !SILVERLIGHT [NonSerialized] #endif Int32 hash; /// /// /// [To be supplied.] /// public static readonly XmlQualifiedName Empty = new XmlQualifiedName(string.Empty); /// /// /// [To be supplied.] /// public XmlQualifiedName() : this(string.Empty, string.Empty) {} /// /// /// [To be supplied.] /// public XmlQualifiedName(string name) : this(name, string.Empty) {} /// /// /// [To be supplied.] /// public XmlQualifiedName(string name, string ns) { this.ns = ns == null ? string.Empty : ns; this.name = name == null ? string.Empty : name; } /// /// /// [To be supplied.] /// public string Namespace { get { return ns; } } /// /// /// [To be supplied.] /// public string Name { get { return name; } } /// /// /// [To be supplied.] /// public override int GetHashCode() { if(hash == 0) { #if !SILVERLIGHT if (hashCodeDelegate == null) { hashCodeDelegate = GetHashCodeDelegate(); } hash = hashCodeDelegate(Name, Name.Length, 0); #else hash = Name.GetHashCode() /*+ Namespace.GetHashCode()*/; // for perf reasons we are not taking ns's hashcode. #endif } return hash; } /// /// /// [To be supplied.] /// public bool IsEmpty { get { return Name.Length == 0 && Namespace.Length == 0; } } /// /// /// [To be supplied.] /// public override string ToString() { return Namespace.Length == 0 ? Name : string.Concat(Namespace, ":" , Name); } /// /// /// [To be supplied.] /// public override bool Equals(object other) { XmlQualifiedName qname; if ((object) this == other) { return true; } qname = other as XmlQualifiedName; if (qname != null) { return (Name == qname.Name && Namespace == qname.Namespace); } return false; } /// /// /// [To be supplied.] /// public static bool operator ==(XmlQualifiedName a, XmlQualifiedName b) { if ((object) a == (object) b) return true; if ((object) a == null || (object) b == null) return false; return (a.Name == b.Name && a.Namespace == b.Namespace); } /// /// /// [To be supplied.] /// public static bool operator !=(XmlQualifiedName a, XmlQualifiedName b) { return !(a == b); } /// /// /// [To be supplied.] /// public static string ToString(string name, string ns) { return ns == null || ns.Length == 0 ? name : ns + ":" + name; } #if !SILVERLIGHT // These methods are not used in Silverlight [SecuritySafeCritical] #if !MOBILE [ReflectionPermission(SecurityAction.Assert, Unrestricted = true)] #endif private static HashCodeOfStringDelegate GetHashCodeDelegate() { // If we are using randomized hashing and we find the Marving hash method, we use that // Otherwise, we use the old string hashing function. if (!IsRandomizedHashingDisabled()) { MethodInfo getHashCodeMethodInfo = typeof(String).GetMethod("InternalMarvin32HashString", BindingFlags.NonPublic | BindingFlags.Static); if (getHashCodeMethodInfo != null) { return (HashCodeOfStringDelegate)Delegate.CreateDelegate(typeof(HashCodeOfStringDelegate), getHashCodeMethodInfo); } // This will fall through and return a delegate to the old hash function Debug.Assert(false, "Randomized hashing is not supported."); } return new HashCodeOfStringDelegate(GetHashCodeOfString); } #if MONO static bool IsRandomizedHashingDisabled () { return false; } #else [SecuritySafeCritical] [RegistryPermission(SecurityAction.Assert, Unrestricted = true)] private static bool IsRandomizedHashingDisabled() { const string regValueName = "DisableRandomizedHashingOnXmlQualifiedName"; bool disableHashing = false; // default value if (!ReadBoolFromXmlRegistrySettings(Registry.CurrentUser, regValueName, ref disableHashing)) { ReadBoolFromXmlRegistrySettings(Registry.LocalMachine, regValueName, ref disableHashing); } return disableHashing; } [SecurityCritical] private static bool ReadBoolFromXmlRegistrySettings(RegistryKey hive, string regValueName, ref bool value) { const string regValuePath = @"SOFTWARE\Microsoft\.NETFramework\XML"; try { using (RegistryKey xmlRegKey = hive.OpenSubKey(regValuePath, false)) { if (xmlRegKey != null) { if (xmlRegKey.GetValueKind(regValueName) == RegistryValueKind.DWord) { value = ((int)xmlRegKey.GetValue(regValueName)) == 1; return true; } } } } catch { /* use the default if we couldn't read the key */ } return false; } #endif private static int GetHashCodeOfString(string s, int length, long additionalEntropy) { // This is the fallback method for calling the regular hashcode method return s.GetHashCode(); } // --------- Some useful internal stuff ----------------- internal void Init(string name, string ns) { Debug.Assert(name != null && ns != null); this.name = name; this.ns = ns; this.hash = 0; } internal void SetNamespace(string ns) { Debug.Assert(ns != null); this.ns = ns; //Not changing hash since ns is not used to compute hashcode } internal void Verify() { XmlConvert.VerifyNCName(name); if (ns.Length != 0) { XmlConvert.ToUri(ns); } } internal void Atomize(XmlNameTable nameTable) { Debug.Assert(name != null); name = nameTable.Add(name); ns = nameTable.Add(ns); } internal static XmlQualifiedName Parse(string s, IXmlNamespaceResolver nsmgr, out string prefix) { string localName; ValidateNames.ParseQNameThrow(s, out prefix, out localName); string uri = nsmgr.LookupNamespace(prefix); if (uri == null) { if (prefix.Length != 0) { throw new XmlException(Res.Xml_UnknownNs, prefix); } else { //Re-map namespace of empty prefix to string.Empty when there is no default namespace declared uri = string.Empty; } } return new XmlQualifiedName(localName, uri); } internal XmlQualifiedName Clone() { return (XmlQualifiedName)MemberwiseClone(); } internal static int Compare(XmlQualifiedName a, XmlQualifiedName b) { if (null == a) { return (null == b) ? 0 : -1; } if (null == b) { return 1; } int i = String.CompareOrdinal(a.Namespace, b.Namespace); if (i == 0) { i = String.CompareOrdinal(a.Name, b.Name); } return i; } #endif } }