1887cf8fe5a3289ccd2014aa47f46955d85509a4
[mono.git] / mcs / class / referencesource / System.Xml / System / Xml / Dom / DomNameTable.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="DomNameTable.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
7
8 using System;
9 using System.Diagnostics;
10 using System.Xml.Schema;
11
12 namespace System.Xml {
13
14     internal class DomNameTable {
15         XmlName[]    entries;
16         int          count;
17         int          mask;
18         XmlDocument  ownerDocument;
19         XmlNameTable nameTable;
20
21         const int InitialSize = 64; // must be a power of two
22
23         public DomNameTable( XmlDocument document ) {
24             ownerDocument = document;
25             nameTable = document.NameTable;
26             entries = new XmlName[InitialSize];
27             mask = InitialSize - 1;
28             Debug.Assert( ( entries.Length & mask ) == 0 );  // entries.Length must be a power of two
29         }
30
31         public XmlName GetName(string prefix, string localName, string ns, IXmlSchemaInfo schemaInfo) { 
32             if (prefix == null) {
33                 prefix = string.Empty;
34             }
35             if (ns == null) {
36                 ns = string.Empty;
37             }
38
39             int hashCode = XmlName.GetHashCode(localName);
40
41             for (XmlName e = entries[hashCode & mask]; e != null; e = e.next) {
42                 if (e.HashCode == hashCode 
43                     && ((object)e.LocalName == (object)localName 
44                         || e.LocalName.Equals(localName)) 
45                     && ((object)e.Prefix == (object)prefix 
46                         || e.Prefix.Equals(prefix)) 
47                     && ((object)e.NamespaceURI == (object)ns 
48                         || e.NamespaceURI.Equals(ns))
49                     && e.Equals(schemaInfo)) {
50                     return e;
51                 }
52             }
53             return null;
54         }
55
56         public XmlName AddName(string prefix, string localName, string ns, IXmlSchemaInfo schemaInfo) { 
57             if (prefix == null) {
58                 prefix = string.Empty;
59             }
60             if (ns == null) {
61                 ns = string.Empty;
62             }
63
64             int hashCode = XmlName.GetHashCode(localName);
65
66             for (XmlName e = entries[hashCode & mask]; e != null; e = e.next) {
67                 if (e.HashCode == hashCode 
68                     && ((object)e.LocalName == (object)localName 
69                         || e.LocalName.Equals(localName)) 
70                     && ((object)e.Prefix == (object)prefix 
71                         || e.Prefix.Equals(prefix)) 
72                     && ((object)e.NamespaceURI == (object)ns 
73                         || e.NamespaceURI.Equals(ns))
74                     && e.Equals(schemaInfo)) {
75                     return e;
76                 }
77             }
78
79             prefix = nameTable.Add(prefix);
80             localName = nameTable.Add(localName);
81             ns = nameTable.Add(ns);
82             int index = hashCode & mask;
83             XmlName name = XmlName.Create(prefix, localName, ns, hashCode, ownerDocument, entries[index], schemaInfo);
84             entries[index] = name;
85
86             if (count++ == mask) {
87                 Grow();
88             }
89
90             return name;
91         }
92
93         private void Grow() {
94             int newMask = mask * 2 + 1;
95             XmlName[] oldEntries = entries;
96             XmlName[] newEntries = new XmlName[newMask+1];
97
98             // use oldEntries.Length to eliminate the rangecheck            
99             for ( int i = 0; i < oldEntries.Length; i++ ) {
100                 XmlName name = oldEntries[i];
101                 while ( name != null ) {
102                     int newIndex = name.HashCode & newMask;
103                     XmlName tmp = name.next;
104                     name.next = newEntries[newIndex];
105                     newEntries[newIndex] = name;
106                     name = tmp;
107                 }
108             }
109             entries = newEntries;
110             mask = newMask;
111         }
112     }
113 }