6 using System.Collections.Generic;
11 /// This tree is populated by the documentation providers, or populated
12 /// from a binary encoding of the tree. The format of the tree is designed
13 /// to minimize the need to load it in full.
16 /* Ideally this class should also be abstracted to let user have something
17 * else than a file as a backing store, a database for instance
21 const long CurrentVersionNumber = 1;
22 public readonly HelpSource HelpSource;
24 FileStream InputStream;
25 BinaryReader InputReader;
27 // This is the node which contains all the other node of the tree
31 /// Load from file constructor
33 public Tree (HelpSource hs, string filename)
36 Encoding utf8 = new UTF8Encoding (false, true);
38 if (!File.Exists (filename)){
39 throw new FileNotFoundException ();
42 InputStream = File.OpenRead (filename);
43 InputReader = new BinaryReader (InputStream, utf8);
44 byte [] sig = InputReader.ReadBytes (4);
47 throw new Exception ("Invalid file format");
49 InputStream.Position = 4;
50 // Try to read version information
51 if (InputReader.ReadInt32 () == -(int)'v')
52 VersionNumber = InputReader.ReadInt64 ();
54 InputStream.Position -= 4;
56 var position = InputReader.ReadInt32 ();
57 rootNode = new Node (this, position);
58 InflateNode (rootNode);
62 /// Tree creation and merged tree constructor
64 public Tree (HelpSource hs, string caption, string url) : this (hs, null, caption, url)
68 public Tree (HelpSource hs, Node parent, string caption, string element)
71 rootNode = parent == null ? new Node (this, caption, element) : new Node (parent, caption, element);
75 /// Saves the tree into the specified file using the help file format.
77 public void Save (string file)
79 Encoding utf8 = new UTF8Encoding (false, true);
80 using (FileStream output = File.OpenWrite (file)){
81 // Skip over the pointer to the first node.
82 output.Position = 4 + 4 + 8 + 4;
84 using (BinaryWriter writer = new BinaryWriter (output, utf8)) {
86 rootNode.Serialize (output, writer);
89 writer.Write (new byte [] { (byte) 'M', (byte) 'o', (byte) 'H', (byte) 'P' });
90 writer.Write (-(int)'v');
91 writer.Write (CurrentVersionNumber);
92 writer.Write (rootNode.Address);
97 public Node RootNode {
103 public long VersionNumber {
108 static bool GoodSig (byte [] sig)
112 return sig [0] == (byte) 'M'
113 && sig [1] == (byte) 'o'
114 && sig [2] == (byte) 'H'
115 && sig [3] == (byte) 'P';
118 public void InflateNode (Node baseNode)
120 var address = baseNode.Address;
124 InputStream.Position = address;
125 baseNode.Deserialize (InputReader);
128 // Nodes use this value to know if they should manually re-sort their child
129 // if they come from an older generator version
130 internal bool ForceResort {
132 return VersionNumber == 0;
137 public static class TreeDumper
141 static void Indent ()
143 for (int i = 0; i < indent; i++)
147 public static void PrintTree (Node node)
150 Console.WriteLine ("{0},{1}\t[PublicUrl: {2}]", node.Element, node.Caption, node.PublicUrl);
151 if (node.Nodes.Count == 0)
155 foreach (Node n in node.Nodes)
160 public static string ExportToTocXml (Node root, string title, string desc)
163 throw new ArgumentNullException ("root");
164 // Return a toc index of sub-nodes
165 StringBuilder buf = new StringBuilder ();
166 var writer = XmlWriter.Create (buf);
167 writer.WriteStartElement ("toc");
168 writer.WriteAttributeString ("title", title ?? string.Empty);
169 writer.WriteElementString ("description", desc ?? string.Empty);
170 writer.WriteStartElement ("list");
171 foreach (Node n in root.Nodes) {
172 writer.WriteStartElement ("item");
173 writer.WriteAttributeString ("url", n.Element);
174 writer.WriteValue (n.Caption);
175 writer.WriteEndElement ();
177 writer.WriteEndElement ();
178 writer.WriteEndElement ();
182 return buf.ToString ();