cache.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. //
  2. // assembly: System
  3. // namespace: System.Text.RegularExpressions
  4. // file: cache.cs
  5. //
  6. // author: Dan Lewis ([email protected])
  7. // (c) 2002
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. using System;
  29. using System.Collections;
  30. namespace System.Text.RegularExpressions {
  31. class FactoryCache {
  32. public FactoryCache (int capacity) {
  33. this.capacity = capacity;
  34. this.factories = new Hashtable (capacity);
  35. this.mru_list = new MRUList ();
  36. }
  37. public void Add (string pattern, RegexOptions options, IMachineFactory factory) {
  38. lock (this) {
  39. Key k = new Key (pattern, options);
  40. while (factories.Count >= capacity) {
  41. object victim = mru_list.Evict ();
  42. if (victim != null)
  43. factories.Remove ((Key)victim);
  44. }
  45. factories[k] = factory;
  46. mru_list.Use (k);
  47. }
  48. }
  49. public IMachineFactory Lookup (string pattern, RegexOptions options) {
  50. lock (this) {
  51. Key k = new Key (pattern, options);
  52. if (factories.Contains (k)) {
  53. mru_list.Use (k);
  54. return (IMachineFactory)factories[k];
  55. }
  56. }
  57. return null;
  58. }
  59. private int capacity;
  60. private Hashtable factories;
  61. private MRUList mru_list;
  62. class Key {
  63. public string pattern;
  64. public RegexOptions options;
  65. public Key (string pattern, RegexOptions options) {
  66. this.pattern = pattern;
  67. this.options = options;
  68. }
  69. public override int GetHashCode () {
  70. return pattern.GetHashCode () ^ (int)options;
  71. }
  72. public override bool Equals (object o) {
  73. if (o == null || !(o is Key))
  74. return false;
  75. Key k = (Key)o;
  76. return options == k.options && pattern.Equals (k.pattern);
  77. }
  78. public override string ToString () {
  79. return "('" + pattern + "', [" + options + "])";
  80. }
  81. }
  82. }
  83. class MRUList {
  84. public MRUList () {
  85. head = tail = null;
  86. }
  87. public void Use (object o) {
  88. Node node;
  89. if (head == null) {
  90. node = new Node (o);
  91. head = tail = node;
  92. return;
  93. }
  94. node = head;
  95. while (node != null && !o.Equals (node.value))
  96. node = node.previous;
  97. if (node == null)
  98. node = new Node (o);
  99. else {
  100. if (node == head)
  101. return;
  102. if (node == tail)
  103. tail = node.next;
  104. else
  105. node.previous.next = node.next;
  106. node.next.previous = node.previous;
  107. }
  108. head.next = node;
  109. node.previous = head;
  110. node.next = null;
  111. head = node;
  112. }
  113. public object Evict () {
  114. if (tail == null)
  115. return null;
  116. object o = tail.value;
  117. tail = tail.next;
  118. if (tail == null)
  119. head = null;
  120. else
  121. tail.previous = null;
  122. return o;
  123. }
  124. private Node head, tail;
  125. private class Node {
  126. public object value;
  127. public Node previous, next;
  128. public Node (object value) {
  129. this.value = value;
  130. }
  131. }
  132. }
  133. }