[runtime] Disable some tests in full-aot mode which cannot be AOTed because of type...
[mono-project.git] / mcs / class / monodoc / Monodoc / Node.cs
blob08452f8c40f25a6f6d3b84db0d69016ffad1d0f7
1 using System;
2 using System.IO;
3 using System.Text;
4 using System.Linq;
5 using System.Xml;
6 using System.Collections;
7 using System.Collections.Generic;
9 namespace Monodoc
11 public
12 #if LEGACY_MODE
13 partial
14 #endif
15 class Node : IComparable<Node>, IComparable
17 readonly Tree parentTree;
18 string caption, element, pubUrl;
19 public bool Documented;
20 bool loaded;
21 Node parent;
22 List<Node> nodes;
23 #if LEGACY_MODE
24 ArrayList legacyNodes;
25 #endif
26 Dictionary<string, Node> childrenLookup;
27 bool elementSort;
28 /* Address has three types of value,
29 * _ 0 is for no on-disk representation
30 * _ >0 is a valid address that is loaded immediately
31 * _ <0 is a valid negated address to indicate lazy loading
33 int address;
35 #if LEGACY_MODE
36 [Obsolete ("Tree inheriting Node is being phased out. Use the `Tree.RootNode' property instead")]
37 public Node (string caption, string element)
39 this.parentTree = (Tree) this;
40 this.caption = caption;
41 this.element = element;
42 parent = null;
44 #endif
46 public Node (Node parent, string caption, string element) : this (parent.Tree, caption, element)
48 this.parent = parent;
51 internal Node (Tree tree, string caption, string element)
53 this.parentTree = tree;
54 this.caption = caption;
55 this.element = element;
56 this.elementSort = parentTree.HelpSource != null && parentTree.HelpSource.SortType == SortType.Element;
59 /// <summary>
60 /// Creates a node from an on-disk representation
61 /// </summary>
62 internal Node (Node parent, int address) : this (parent.parentTree, address)
64 this.parent = parent;
67 internal Node (Tree tree, int address)
69 this.address = address;
70 this.parentTree = tree;
71 this.elementSort = parentTree.HelpSource != null && parentTree.HelpSource.SortType == SortType.Element;
72 if (address > 0)
73 LoadNode ();
76 /* This is solely used for MatchNode to check for equality */
77 internal Node ()
81 void LoadNode ()
83 parentTree.InflateNode (this);
84 if (parent != null)
85 parent.RegisterFullNode (this);
88 public void AddNode (Node n)
90 nodes.Add (n);
91 n.parent = this;
92 n.Documented = true;
93 RegisterFullNode (n);
96 public void DeleteNode (Node n)
98 nodes.Remove (n);
99 if (!string.IsNullOrEmpty (n.element))
100 childrenLookup.Remove (n.element);
103 // When a child node is inflated, it calls this method
104 // so that we can add it to our lookup for quick search
105 void RegisterFullNode (Node child)
107 if (childrenLookup == null)
108 childrenLookup = new Dictionary<string, Node> ();
109 if (!string.IsNullOrEmpty (child.element))
110 childrenLookup[child.element] = child;
113 [Obsolete ("Use ChildNodes")]
114 public ArrayList Nodes {
115 get {
116 if (legacyNodes == null)
117 legacyNodes = new ArrayList (ChildNodes as ICollection);
118 return legacyNodes;
122 public IList<Node> ChildNodes {
123 get {
124 EnsureLoaded ();
125 return nodes != null ? nodes : new List<Node> ();
129 public string Element {
130 get {
131 EnsureLoaded ();
132 return element;
134 set {
135 element = value;
139 public string Caption {
140 get {
141 EnsureLoaded ();
142 return caption;
144 internal set {
145 caption = value;
149 public Node Parent {
150 get {
151 return parent;
155 public Tree Tree {
156 get {
157 return parentTree;
161 internal int Address {
162 get {
163 return address;
165 #if LEGACY_MODE
166 set {
167 address = value;
169 #endif
172 /// <summary>
173 /// Creates a new node, in the locator entry point, and with
174 /// a user visible caption of @caption
175 /// </summary>
176 public Node CreateNode (string c_caption, string c_element)
178 EnsureNodes ();
179 if (string.IsNullOrEmpty (c_caption))
180 throw new ArgumentNullException ("c_caption");
181 if (string.IsNullOrEmpty (c_element))
182 throw new ArgumentNullException ("c_element");
184 Node t = new Node (this, c_caption, c_element);
185 nodes.Add (t);
186 childrenLookup[c_element] = t;
188 return t;
191 public Node GetOrCreateNode (string c_caption, string c_element)
193 if (nodes == null)
194 return CreateNode (c_caption, c_element);
195 if (childrenLookup.Count != nodes.Count || (nodes.Count == 0 && childrenLookup.Count != nodes.Capacity))
196 UpdateLookup ();
198 Node result;
199 if (!childrenLookup.TryGetValue (c_element, out result))
200 result = CreateNode (c_caption, c_element);
201 return result;
204 public void EnsureNodes ()
206 if (nodes == null) {
207 nodes = new List<Node> ();
208 childrenLookup = new Dictionary<string, Node> ();
212 public void EnsureLoaded ()
214 if (address < 0 && !loaded) {
215 LoadNode ();
216 loaded = true;
220 void UpdateLookup ()
222 foreach (var node in nodes)
223 childrenLookup[node.Element] = node;
226 public bool IsLeaf {
227 get {
228 return nodes == null || nodes.Count == 0;
232 void EncodeInt (BinaryWriter writer, int value)
234 do {
235 int high = (value >> 7) & 0x01ffffff;
236 byte b = (byte)(value & 0x7f);
238 if (high != 0) {
239 b = (byte)(b | 0x80);
242 writer.Write(b);
243 value = high;
244 } while(value != 0);
247 int DecodeInt (BinaryReader reader)
249 int ret = 0;
250 int shift = 0;
251 byte b;
253 do {
254 b = reader.ReadByte();
256 ret = ret | ((b & 0x7f) << shift);
257 shift += 7;
258 } while ((b & 0x80) == 0x80);
260 return ret;
263 internal void Deserialize (BinaryReader reader)
265 int count = DecodeInt (reader);
266 element = reader.ReadString ();
267 caption = reader.ReadString ();
269 if (count == 0)
270 return;
272 nodes = new List<Node> (count);
273 for (int i = 0; i < count; i++) {
274 int child_address = DecodeInt (reader);
276 Node t = new Node (this, -child_address);
277 nodes.Add (t);
280 if (parentTree.ForceResort)
281 nodes.Sort ();
284 internal void Serialize (FileStream output, BinaryWriter writer)
286 if (nodes != null)
287 foreach (Node child in nodes)
288 child.Serialize (output, writer);
290 address = (int) output.Position;
291 EncodeInt (writer, nodes == null ? 0 : (int) nodes.Count);
292 writer.Write (element);
293 writer.Write (caption);
295 if (nodes != null)
296 foreach (Node child in nodes)
297 EncodeInt (writer, child.address);
300 public void Sort ()
302 if (nodes != null)
303 nodes.Sort ();
306 internal string GetInternalUrl ()
308 EnsureLoaded ();
309 if (element.IndexOf (":") != -1 || parent == null)
310 return element;
312 var parentUrl = parent.GetInternalUrl ();
313 return parentUrl.EndsWith ("/") ? parentUrl + element : parentUrl + "/" + element;
316 public string PublicUrl {
317 get {
318 if (pubUrl != null)
319 return pubUrl;
320 return pubUrl = parentTree.HelpSource != null ? parentTree.HelpSource.GetPublicUrl (this) : GetInternalUrl ();
324 int IComparable.CompareTo (object obj)
326 Node other = obj as Node;
327 if (other == null)
328 return -1;
329 return CompareToInternal (other);
332 int IComparable<Node>.CompareTo (Node obj)
334 return CompareToInternal (obj);
337 int CompareToInternal (Node other)
339 EnsureLoaded ();
340 other.EnsureLoaded ();
342 var cap1 = elementSort ? element : caption;
343 var cap2 = elementSort ? other.element : other.caption;
345 /* Some node (notably from ecmaspec) have number prepended to them
346 * which we need to sort better by padding them to the same number
347 * of digits
349 if (char.IsDigit (cap1[0]) && char.IsDigit (cap2[0])) {
350 int c1 = cap1.TakeWhile (char.IsDigit).Count ();
351 int c2 = cap2.TakeWhile (char.IsDigit).Count ();
353 if (c1 != c2) {
354 cap1 = cap1.PadLeft (cap1.Length + Math.Max (0, c2 - c1), '0');
355 cap2 = cap2.PadLeft (cap2.Length + Math.Max (0, c1 - c2), '0');
359 return string.Compare (cap1, cap2, StringComparison.Ordinal);
363 internal static class IListExtensions
365 // TODO: if the backing store ever change from List<T>, we need to tune these methods to have a fallback mechanism
366 public static int BinarySearch<T> (this IList<T> ilist, T item)
368 var list = ilist as List<T>;
369 if (list == null)
370 throw new NotSupportedException ();
371 return list.BinarySearch (item);
374 public static int BinarySearch<T> (this IList<T> ilist, T item, IComparer<T> comparer)
376 var list = ilist as List<T>;
377 if (list == null)
378 throw new NotSupportedException ();
379 return list.BinarySearch (item, comparer);