2 // System.Xml.NameTable.cs
5 // Duncan Mak (duncan@ximian.com)
6 // Ben Maurer (bmaurer@users.sourceforge.net)
13 using System.Collections;
15 namespace System.Xml {
17 // This class implements the name table as a simple
18 // hashtable, using buckets and a linked list.
20 public class NameTable : XmlNameTable {
22 const int INITIAL_BUCKETS = 2 << 6; // 64
24 int count = INITIAL_BUCKETS;
25 Entry [] buckets = new Entry [INITIAL_BUCKETS];
28 public NameTable () {}
35 public Entry (string str, int hash, Entry next)
38 this.len = str.Length;
44 public override string Add (char [] key, int start, int len)
46 if (((0 > start) && (start >= key.Length))
47 || ((0 > len) && (len >= key.Length - len)))
48 throw new IndexOutOfRangeException ("The Index is out of range.");
50 if (len == 0) return String.Empty;
53 // This is from the String.Gethash () icall
54 for (int i = start; i < len; i++)
55 h = (h << 5) - h + key [i];
60 for (Entry e = buckets [h % count]; e != null; e = e.next) {
61 if (e.hash == h && e.len == len && StrEqArray (e.str, key, start))
64 return AddEntry (new string (key, start, len), h);
67 public override string Add (string key)
69 if (key == null) throw new ArgumentNullException ("key");
71 int keyLen = key.Length;
72 if (keyLen == 0) return String.Empty;
75 // This is from the String.Gethash () icall
76 for (int i = 0; i < keyLen; i++)
77 h = (h << 5) - h + key [i];
82 for (Entry e = buckets [h % count]; e != null; e = e.next) {
83 if (e.hash == h && e.len == key.Length && e.str == key)
87 return AddEntry (key, h);
90 public override string Get (char [] key, int start, int len)
92 if (((0 > start) && (start >= key.Length))
93 || ((0 > len) && (len >= key.Length - len)))
94 throw new IndexOutOfRangeException ("The Index is out of range.");
96 if (len == 0) return String.Empty;
99 // This is from the String.Gethash () icall
100 for (int i = start; i < len; i++)
101 h = (h << 5) - h + key [i];
105 for (Entry e = buckets [h % count]; e != null; e = e.next) {
106 if (e.hash == h && e.len == len && StrEqArray (e.str, key, start))
113 public override string Get (string value) {
114 if (value == null) throw new ArgumentNullException ("value");
116 int valLen = value.Length;
117 if (valLen == 0) return String.Empty;
120 // This is from the String.Gethash () icall
121 for (int i = 0; i < valLen; i++)
122 h = (h << 5) - h + value [i];
126 for (Entry e = buckets [h % count]; e != null; e = e.next) {
127 if (e.hash == h && e.len == value.Length && e.str == value)
134 string AddEntry (string str, int hash)
136 int bucket = hash % count;
137 buckets [bucket] = new Entry (str, hash, buckets [bucket]);
139 // Grow whenever we double in size
140 if (size++ == count) {
142 int csub1 = count - 1;
144 Entry [] newBuckets = new Entry [count];
145 foreach (Entry root in buckets) {
148 int newLoc = e.hash & csub1;
150 e.next = newBuckets [newLoc];
151 newBuckets [newLoc] = e;
156 buckets = newBuckets;
162 static bool StrEqArray (string str, char [] str2, int start)
164 for (int i = 0; i < str.Length; i++) {
165 if (str [i] != str2 [start + i])