-revert janderwalds change until because it breaks the gcc 4.x build
[reactos.git] / irc / TechBot / CHMLibrary / CHMDecoding / CHMTopics.cs
1 using System;
2 using System.IO;
3 using System.Collections;
4 using System.Collections.Specialized;
5
6 namespace HtmlHelp.ChmDecoding
7 {
8 /// <summary>
9 /// The class <c>CHMTopics</c> implements functionality to decode the #TOPICS internal file
10 /// </summary>
11 internal sealed class CHMTopics : IDisposable
12 {
13 /// <summary>
14 /// Internal flag specifying if the object is going to be disposed
15 /// </summary>
16 private bool disposed = false;
17 /// <summary>
18 /// Internal member storing the binary file data
19 /// </summary>
20 private byte[] _binaryFileData = null;
21 /// <summary>
22 /// Internal member storing the associated chmfile object
23 /// </summary>
24 private CHMFile _associatedFile = null;
25 /// <summary>
26 /// Internal member storing the topic list
27 /// </summary>
28 private ArrayList _topicTable = new ArrayList();
29
30 /// <summary>
31 /// Constructor of the class
32 /// </summary>
33 /// <param name="binaryFileData">binary file data of the #TOPICS file</param>
34 /// <param name="associatedFile">associated chm file</param>
35 public CHMTopics(byte[] binaryFileData, CHMFile associatedFile)
36 {
37 _binaryFileData = binaryFileData;
38 _associatedFile = associatedFile;
39 DecodeData();
40
41 // clear internal binary data after extraction
42 _binaryFileData = null;
43 }
44
45
46 /// <summary>
47 /// Standard constructor
48 /// </summary>
49 internal CHMTopics()
50 {
51 }
52
53 #region Data dumping
54 /// <summary>
55 /// Dump the class data to a binary writer
56 /// </summary>
57 /// <param name="writer">writer to write the data</param>
58 internal void Dump(ref BinaryWriter writer)
59 {
60 writer.Write( _topicTable.Count );
61 foreach(TopicEntry curItem in _topicTable)
62 {
63 curItem.Dump(ref writer);
64 }
65 }
66
67 /// <summary>
68 /// Reads the object data from a dump store
69 /// </summary>
70 /// <param name="reader">reader to read the data</param>
71 internal void ReadDump(ref BinaryReader reader)
72 {
73 int i=0;
74 int nCnt = reader.ReadInt32();
75
76 for(i=0; i<nCnt;i++)
77 {
78 TopicEntry newItem = new TopicEntry();
79 newItem.SetCHMFile(_associatedFile);
80 newItem.ReadDump(ref reader);
81 _topicTable.Add(newItem);
82 }
83 }
84
85 /// <summary>
86 /// Sets the associated CHMFile instance
87 /// </summary>
88 /// <param name="associatedFile">instance to set</param>
89 internal void SetCHMFile(CHMFile associatedFile)
90 {
91 _associatedFile = associatedFile;
92
93 foreach(TopicEntry curEntry in _topicTable)
94 {
95 curEntry.SetCHMFile(associatedFile);
96 }
97 }
98 #endregion
99
100 /// <summary>
101 /// Decodes the binary file data and fills the internal properties
102 /// </summary>
103 /// <returns>true if succeeded</returns>
104 private bool DecodeData()
105 {
106 bool bRet = true;
107
108 MemoryStream memStream = new MemoryStream(_binaryFileData);
109 BinaryReader binReader = new BinaryReader(memStream);
110
111 int nCurOffset = 0;
112
113 while( (memStream.Position < memStream.Length) && (bRet) )
114 {
115 int entryOffset = nCurOffset;
116 int tocIdx = binReader.ReadInt32();
117 int titleOffset = binReader.ReadInt32();
118 int urltablOffset = binReader.ReadInt32();
119 int visibilityMode = binReader.ReadInt16();
120 int unknownMode = binReader.ReadInt16();
121
122 TopicEntry newEntry = new TopicEntry(entryOffset, tocIdx, titleOffset, urltablOffset, visibilityMode, unknownMode, _associatedFile);
123 _topicTable.Add( newEntry );
124
125 nCurOffset = (int)memStream.Position;
126 }
127
128 return bRet;
129 }
130
131 /// <summary>
132 /// Gets the arraylist containing all topic entries.
133 /// </summary>
134 public ArrayList TopicTable
135 {
136 get
137 {
138 return _topicTable;
139 }
140 }
141
142 /// <summary>
143 /// Gets the topic entry of a given offset
144 /// </summary>
145 public TopicEntry this[int offset]
146 {
147 get
148 {
149 foreach(TopicEntry curEntry in _topicTable)
150 if(curEntry.EntryOffset == offset)
151 return curEntry;
152
153 return null;
154 }
155 }
156
157 /// <summary>
158 /// Searches a topic by the locale name
159 /// </summary>
160 /// <param name="locale">locale name to search</param>
161 /// <returns>The topicentry instance if found, otherwise null</returns>
162 public TopicEntry GetByLocale(string locale)
163 {
164 foreach(TopicEntry curEntry in TopicTable)
165 {
166 if(curEntry.Locale.ToLower() == locale.ToLower())
167 return curEntry;
168 }
169
170 return null;
171 }
172
173 /// <summary>
174 /// Searches the topics for all files with a given file extension
175 /// </summary>
176 /// <param name="fileExtension">extension to search</param>
177 /// <returns>An arraylist of TopicEntry instances or null if no topic was found</returns>
178 public ArrayList GetByExtension(string fileExtension)
179 {
180 ArrayList arrRet = new ArrayList();
181
182 foreach(TopicEntry curEntry in TopicTable)
183 {
184 if(curEntry.Locale.ToLower().EndsWith(fileExtension.ToLower()))
185 arrRet.Add(curEntry);
186 }
187
188 if(arrRet.Count > 0)
189 return arrRet;
190
191 return null;
192 }
193
194 /// <summary>
195 /// Implement IDisposable.
196 /// </summary>
197 public void Dispose()
198 {
199 Dispose(true);
200 // This object will be cleaned up by the Dispose method.
201 // Therefore, you should call GC.SupressFinalize to
202 // take this object off the finalization queue
203 // and prevent finalization code for this object
204 // from executing a second time.
205 GC.SuppressFinalize(this);
206 }
207
208 /// <summary>
209 /// Dispose(bool disposing) executes in two distinct scenarios.
210 /// If disposing equals true, the method has been called directly
211 /// or indirectly by a user's code. Managed and unmanaged resources
212 /// can be disposed.
213 /// If disposing equals false, the method has been called by the
214 /// runtime from inside the finalizer and you should not reference
215 /// other objects. Only unmanaged resources can be disposed.
216 /// </summary>
217 /// <param name="disposing">disposing flag</param>
218 private void Dispose(bool disposing)
219 {
220 // Check to see if Dispose has already been called.
221 if(!this.disposed)
222 {
223 // If disposing equals true, dispose all managed
224 // and unmanaged resources.
225 if(disposing)
226 {
227 // Dispose managed resources.
228 _binaryFileData = null;
229 _topicTable=null;
230 }
231 }
232 disposed = true;
233 }
234 }
235 }