New/Updated test cases. Fixed TraceTest so that it isn't causing test
[mono.git] / mcs / class / System / System.Text.RegularExpressions / cache.cs
1 //\r
2 // assembly:    System\r
3 // namespace:   System.Text.RegularExpressions\r
4 // file:        cache.cs\r
5 //\r
6 // author:      Dan Lewis (dlewis@gmx.co.uk)\r
7 //              (c) 2002\r
8 \r
9 using System;\r
10 using System.Collections;\r
11 \r
12 namespace System.Text.RegularExpressions {\r
13 \r
14         class FactoryCache {\r
15                 public FactoryCache (int capacity) {\r
16                         this.capacity = capacity;\r
17                         this.factories = new Hashtable (capacity);\r
18                         this.mru_list = new MRUList ();\r
19                 }\r
20 \r
21                 public void Add (string pattern, RegexOptions options, IMachineFactory factory) {\r
22                         lock (this) {\r
23                                 Key k = new Key (pattern, options);\r
24 \r
25                                 while (factories.Count >= capacity) {\r
26                                         object victim = mru_list.Evict ();\r
27                                         if (victim != null)\r
28                                                 factories.Remove ((Key)victim);\r
29                                 }\r
30                                 \r
31                                 factories[k] = factory;\r
32                                 mru_list.Use (k);\r
33                         }\r
34                 }\r
35 \r
36                 public IMachineFactory Lookup (string pattern, RegexOptions options) {\r
37                         lock (this) {\r
38                                 Key k = new Key (pattern, options);\r
39                                 if (factories.Contains (k)) {\r
40                                         mru_list.Use (k);\r
41                                         return (IMachineFactory)factories[k];\r
42                                 }\r
43                         }\r
44 \r
45                         return null;\r
46                 }\r
47 \r
48                 private int capacity;\r
49                 private Hashtable factories;\r
50                 private MRUList mru_list;\r
51 \r
52                 class Key {\r
53                         public string pattern;\r
54                         public RegexOptions options;\r
55 \r
56                         public Key (string pattern, RegexOptions options) {\r
57                                 this.pattern = pattern;\r
58                                 this.options = options;\r
59                         }\r
60                         \r
61                         public override int GetHashCode () {\r
62                                 return pattern.GetHashCode () ^ (int)options;\r
63                         }\r
64 \r
65                         public override bool Equals (object o) {\r
66                                 if (o == null || !(o is Key))\r
67                                         return false;\r
68 \r
69                                 Key k = (Key)o;\r
70                                 return options == k.options && pattern.Equals (k.pattern);\r
71                         }\r
72 \r
73                         public override string ToString () {\r
74                                 return "('" + pattern + "', [" + options + "])";\r
75                         }\r
76                 }\r
77         }\r
78 \r
79         class MRUList {\r
80                 public MRUList () {\r
81                         head = tail = null;\r
82                 }\r
83 \r
84                 public void Use (object o) {\r
85                         Node node;\r
86 \r
87                         if (head == null) {\r
88                                 node = new Node (o);\r
89                                 head = tail = node;\r
90                                 return;\r
91                         }\r
92 \r
93                         node = head;\r
94                         while (node != null && !o.Equals (node.value))\r
95                                 node = node.previous;\r
96 \r
97                         if (node == null)\r
98                                 node = new Node (o);\r
99                         else {\r
100                                 if (node == head)\r
101                                         return;\r
102 \r
103                                 if (node == tail)\r
104                                         tail = node.next;\r
105                                 else\r
106                                         node.previous.next = node.next;\r
107 \r
108                                 node.next.previous = node.previous;\r
109                         }\r
110 \r
111                         head.next = node;\r
112                         node.previous = head;\r
113                         node.next = null;\r
114                         head = node;\r
115                 }\r
116 \r
117                 public object Evict () {\r
118                         if (tail == null)\r
119                                 return null;\r
120 \r
121                         object o = tail.value;\r
122                         tail = tail.next;\r
123 \r
124                         if (tail == null)\r
125                                 head = null;\r
126                         else\r
127                                 tail.previous = null;\r
128 \r
129                         return o;\r
130                 }\r
131 \r
132                 private Node head, tail;\r
133 \r
134                 private class Node {\r
135                         public object value;\r
136                         public Node previous, next;\r
137 \r
138                         public Node (object value) {\r
139                                 this.value = value;\r
140                         }\r
141                 }\r
142         }\r
143 }\r