NameTable.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. for (int i = start; i < len; i++)
  45. h = (h << 5) - h + key [i];
  46. // h must be be >= 0
  47. h &= 0x7FFFFFFF;
  48. for (Entry e = buckets [h % count]; e != null; e = e.next) {
  49. if (e.hash == h && e.len == len && StrEqArray (e.str, key, start))
  50. return e.str;
  51. }
  52. return AddEntry (new string (key, start, len), h);
  53. }
  54. public override string Add (string key)
  55. {
  56. if (key == null) throw new ArgumentNullException ("key");
  57. int keyLen = key.Length;
  58. if (keyLen == 0) return String.Empty;
  59. int h = 0;
  60. // This is from the String.Gethash () icall
  61. for (int i = 0; i < keyLen; i++)
  62. h = (h << 5) - h + key [i];
  63. // h must be be >= 0
  64. h &= 0x7FFFFFFF;
  65. for (Entry e = buckets [h % count]; e != null; e = e.next) {
  66. if (e.hash == h && e.len == key.Length && e.str == key)
  67. return e.str;
  68. }
  69. return AddEntry (key, h);
  70. }
  71. public override string Get (char [] key, int start, int len)
  72. {
  73. if (((0 > start) && (start >= key.Length))
  74. || ((0 > len) && (len >= key.Length - len)))
  75. throw new IndexOutOfRangeException ("The Index is out of range.");
  76. if (len == 0) return String.Empty;
  77. int h = 0;
  78. // This is from the String.Gethash () icall
  79. for (int i = start; i < len; i++)
  80. h = (h << 5) - h + key [i];
  81. // h must be be >= 0
  82. h &= 0x7FFFFFFF;
  83. for (Entry e = buckets [h % count]; e != null; e = e.next) {
  84. if (e.hash == h && e.len == len && StrEqArray (e.str, key, start))
  85. return e.str;
  86. }
  87. return null;
  88. }
  89. public override string Get (string value) {
  90. if (value == null) throw new ArgumentNullException ("value");
  91. int valLen = value.Length;
  92. if (valLen == 0) return String.Empty;
  93. int h = 0;
  94. // This is from the String.Gethash () icall
  95. for (int i = 0; i < valLen; i++)
  96. h = (h << 5) - h + value [i];
  97. // h must be be >= 0
  98. h &= 0x7FFFFFFF;
  99. for (Entry e = buckets [h % count]; e != null; e = e.next) {
  100. if (e.hash == h && e.len == value.Length && e.str == value)
  101. return e.str;
  102. }
  103. return null;
  104. }
  105. string AddEntry (string str, int hash)
  106. {
  107. int bucket = hash % count;
  108. buckets [bucket] = new Entry (str, hash, buckets [bucket]);
  109. // Grow whenever we double in size
  110. if (size++ == count) {
  111. count <<= 1;
  112. int csub1 = count - 1;
  113. Entry [] newBuckets = new Entry [count];
  114. for (int i = 0; i < buckets.Length; i++) {
  115. Entry root = buckets [i];
  116. Entry e = root;
  117. while (e != null) {
  118. int newLoc = e.hash & csub1;
  119. Entry n = e.next;
  120. e.next = newBuckets [newLoc];
  121. newBuckets [newLoc] = e;
  122. e = n;
  123. }
  124. }
  125. buckets = newBuckets;
  126. }
  127. return str;
  128. }
  129. static bool StrEqArray (string str, char [] str2, int start)
  130. {
  131. for (int i = 0; i < str.Length; i++) {
  132. if (str [i] != str2 [start + i])
  133. return false;
  134. }
  135. return true;
  136. }
  137. }
  138. }