NameTable.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. //
  2. // System.Xml.NameTable.cs
  3. //
  4. // Authors:
  5. // Duncan Mak ([email protected])
  6. // Ben Maurer ([email protected])
  7. //
  8. // (C) Ximian, Inc.
  9. // (C) 2003 Ben Maurer
  10. //
  11. using System;
  12. using System.Collections;
  13. namespace System.Xml {
  14. //
  15. // This class implements the name table as a simple
  16. // hashtable, using buckets and a linked list.
  17. //
  18. public class NameTable : XmlNameTable {
  19. const int INITIAL_BUCKETS = 2 << 6; // 64
  20. int count = INITIAL_BUCKETS;
  21. Entry [] buckets = new Entry [INITIAL_BUCKETS];
  22. int size;
  23. public NameTable () {}
  24. class Entry {
  25. public string str;
  26. public int hash, len;
  27. public Entry next;
  28. public Entry (string str, int hash, Entry next)
  29. {
  30. this.str = str;
  31. this.len = str.Length;
  32. this.hash = hash;
  33. this.next = next;
  34. }
  35. }
  36. public override string Add (char [] key, int start, int len)
  37. {
  38. if (((0 > start) && (start >= key.Length))
  39. || ((0 > len) && (len >= key.Length - len)))
  40. throw new IndexOutOfRangeException ("The Index is out of range.");
  41. if (len == 0) return String.Empty;
  42. int h = 0;
  43. // This is from the String.Gethash () icall
  44. int end = start + len;
  45. for (int i = start; i < end; i++)
  46. h = (h << 5) - h + key [i];
  47. // h must be be >= 0
  48. h &= 0x7FFFFFFF;
  49. for (Entry e = buckets [h % count]; e != null; e = e.next) {
  50. if (e.hash == h && e.len == len && StrEqArray (e.str, key, start))
  51. return e.str;
  52. }
  53. return AddEntry (new string (key, start, len), h);
  54. }
  55. public override string Add (string key)
  56. {
  57. if (key == null) throw new ArgumentNullException ("key");
  58. int keyLen = key.Length;
  59. if (keyLen == 0) return String.Empty;
  60. int h = 0;
  61. // This is from the String.Gethash () icall
  62. for (int i = 0; i < keyLen; i++)
  63. h = (h << 5) - h + key [i];
  64. // h must be be >= 0
  65. h &= 0x7FFFFFFF;
  66. for (Entry e = buckets [h % count]; e != null; e = e.next) {
  67. if (e.hash == h && e.len == key.Length && e.str == key)
  68. return e.str;
  69. }
  70. return AddEntry (key, h);
  71. }
  72. public override string Get (char [] key, int start, int len)
  73. {
  74. if (((0 > start) && (start >= key.Length))
  75. || ((0 > len) && (len >= key.Length - len)))
  76. throw new IndexOutOfRangeException ("The Index is out of range.");
  77. if (len == 0) return String.Empty;
  78. int h = 0;
  79. // This is from the String.Gethash () icall
  80. int end = start + len;
  81. for (int i = start; i < end; i++)
  82. h = (h << 5) - h + key [i];
  83. // h must be be >= 0
  84. h &= 0x7FFFFFFF;
  85. for (Entry e = buckets [h % count]; e != null; e = e.next) {
  86. if (e.hash == h && e.len == len && StrEqArray (e.str, key, start))
  87. return e.str;
  88. }
  89. return null;
  90. }
  91. public override string Get (string value) {
  92. if (value == null) throw new ArgumentNullException ("value");
  93. int valLen = value.Length;
  94. if (valLen == 0) return String.Empty;
  95. int h = 0;
  96. // This is from the String.Gethash () icall
  97. for (int i = 0; i < valLen; i++)
  98. h = (h << 5) - h + value [i];
  99. // h must be be >= 0
  100. h &= 0x7FFFFFFF;
  101. for (Entry e = buckets [h % count]; e != null; e = e.next) {
  102. if (e.hash == h && e.len == value.Length && e.str == value)
  103. return e.str;
  104. }
  105. return null;
  106. }
  107. string AddEntry (string str, int hash)
  108. {
  109. int bucket = hash % count;
  110. buckets [bucket] = new Entry (str, hash, buckets [bucket]);
  111. // Grow whenever we double in size
  112. if (size++ == count) {
  113. count <<= 1;
  114. int csub1 = count - 1;
  115. Entry [] newBuckets = new Entry [count];
  116. for (int i = 0; i < buckets.Length; i++) {
  117. Entry root = buckets [i];
  118. Entry e = root;
  119. while (e != null) {
  120. int newLoc = e.hash & csub1;
  121. Entry n = e.next;
  122. e.next = newBuckets [newLoc];
  123. newBuckets [newLoc] = e;
  124. e = n;
  125. }
  126. }
  127. buckets = newBuckets;
  128. }
  129. return str;
  130. }
  131. static bool StrEqArray (string str, char [] str2, int start)
  132. {
  133. for (int i = 0; i < str.Length; i++) {
  134. if (str [i] != str2 [start + i])
  135. return false;
  136. }
  137. return true;
  138. }
  139. }
  140. }