Fix watchos tests for system.data (#6600)
[mono-project.git] / docs / HtmlAgilityPack / MixedCodeDocument.cs
blobf12ac4521bcb935fc0aac570208d8fd0b2704a27
1 // HtmlAgilityPack V1.0 - Simon Mourier <simon underscore mourier at hotmail dot com>
2 using System;
3 using System.IO;
4 using System.Text;
6 namespace HtmlAgilityPack
8 /// <summary>
9 /// Represents a document with mixed code and text. ASP, ASPX, JSP, are good example of such documents.
10 /// </summary>
11 public class MixedCodeDocument
13 #region Fields
15 private int _c;
16 internal MixedCodeDocumentFragmentList _codefragments;
17 private MixedCodeDocumentFragment _currentfragment;
18 internal MixedCodeDocumentFragmentList _fragments;
19 private int _index;
20 private int _line;
21 private int _lineposition;
22 private ParseState _state;
23 private Encoding _streamencoding;
24 internal string _text;
25 internal MixedCodeDocumentFragmentList _textfragments;
27 /// <summary>
28 /// Gets or sets the token representing code end.
29 /// </summary>
30 public string TokenCodeEnd = "%>";
32 /// <summary>
33 /// Gets or sets the token representing code start.
34 /// </summary>
35 public string TokenCodeStart = "<%";
37 /// <summary>
38 /// Gets or sets the token representing code directive.
39 /// </summary>
40 public string TokenDirective = "@";
42 /// <summary>
43 /// Gets or sets the token representing response write directive.
44 /// </summary>
45 public string TokenResponseWrite = "Response.Write ";
48 private string TokenTextBlock = "TextBlock({0})";
50 #endregion
52 #region Constructors
54 /// <summary>
55 /// Creates a mixed code document instance.
56 /// </summary>
57 public MixedCodeDocument()
59 _codefragments = new MixedCodeDocumentFragmentList(this);
60 _textfragments = new MixedCodeDocumentFragmentList(this);
61 _fragments = new MixedCodeDocumentFragmentList(this);
64 #endregion
66 #region Properties
68 /// <summary>
69 /// Gets the code represented by the mixed code document seen as a template.
70 /// </summary>
71 public string Code
73 get
75 string s = "";
76 int i = 0;
77 foreach (MixedCodeDocumentFragment frag in _fragments)
79 switch (frag._type)
81 case MixedCodeDocumentFragmentType.Text:
82 s += TokenResponseWrite + string.Format(TokenTextBlock, i) + "\n";
83 i++;
84 break;
86 case MixedCodeDocumentFragmentType.Code:
87 s += ((MixedCodeDocumentCodeFragment) frag).Code + "\n";
88 break;
91 return s;
95 /// <summary>
96 /// Gets the list of code fragments in the document.
97 /// </summary>
98 public MixedCodeDocumentFragmentList CodeFragments
100 get { return _codefragments; }
103 /// <summary>
104 /// Gets the list of all fragments in the document.
105 /// </summary>
106 public MixedCodeDocumentFragmentList Fragments
108 get { return _fragments; }
111 /// <summary>
112 /// Gets the encoding of the stream used to read the document.
113 /// </summary>
114 public Encoding StreamEncoding
116 get { return _streamencoding; }
119 /// <summary>
120 /// Gets the list of text fragments in the document.
121 /// </summary>
122 public MixedCodeDocumentFragmentList TextFragments
124 get { return _textfragments; }
127 #endregion
129 #region Public Methods
131 /// <summary>
132 /// Create a code fragment instances.
133 /// </summary>
134 /// <returns>The newly created code fragment instance.</returns>
135 public MixedCodeDocumentCodeFragment CreateCodeFragment()
137 return (MixedCodeDocumentCodeFragment) CreateFragment(MixedCodeDocumentFragmentType.Code);
140 /// <summary>
141 /// Create a text fragment instances.
142 /// </summary>
143 /// <returns>The newly created text fragment instance.</returns>
144 public MixedCodeDocumentTextFragment CreateTextFragment()
146 return (MixedCodeDocumentTextFragment) CreateFragment(MixedCodeDocumentFragmentType.Text);
149 /// <summary>
150 /// Loads a mixed code document from a stream.
151 /// </summary>
152 /// <param name="stream">The input stream.</param>
153 public void Load(Stream stream)
155 Load(new StreamReader(stream));
158 /// <summary>
159 /// Loads a mixed code document from a stream.
160 /// </summary>
161 /// <param name="stream">The input stream.</param>
162 /// <param name="detectEncodingFromByteOrderMarks">Indicates whether to look for byte order marks at the beginning of the file.</param>
163 public void Load(Stream stream, bool detectEncodingFromByteOrderMarks)
165 Load(new StreamReader(stream, detectEncodingFromByteOrderMarks));
168 /// <summary>
169 /// Loads a mixed code document from a stream.
170 /// </summary>
171 /// <param name="stream">The input stream.</param>
172 /// <param name="encoding">The character encoding to use.</param>
173 public void Load(Stream stream, Encoding encoding)
175 Load(new StreamReader(stream, encoding));
178 /// <summary>
179 /// Loads a mixed code document from a stream.
180 /// </summary>
181 /// <param name="stream">The input stream.</param>
182 /// <param name="encoding">The character encoding to use.</param>
183 /// <param name="detectEncodingFromByteOrderMarks">Indicates whether to look for byte order marks at the beginning of the file.</param>
184 public void Load(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks)
186 Load(new StreamReader(stream, encoding, detectEncodingFromByteOrderMarks));
189 /// <summary>
190 /// Loads a mixed code document from a stream.
191 /// </summary>
192 /// <param name="stream">The input stream.</param>
193 /// <param name="encoding">The character encoding to use.</param>
194 /// <param name="detectEncodingFromByteOrderMarks">Indicates whether to look for byte order marks at the beginning of the file.</param>
195 /// <param name="buffersize">The minimum buffer size.</param>
196 public void Load(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int buffersize)
198 Load(new StreamReader(stream, encoding, detectEncodingFromByteOrderMarks, buffersize));
201 /// <summary>
202 /// Loads a mixed code document from a file.
203 /// </summary>
204 /// <param name="path">The complete file path to be read.</param>
205 public void Load(string path)
207 Load(new StreamReader(path));
210 /// <summary>
211 /// Loads a mixed code document from a file.
212 /// </summary>
213 /// <param name="path">The complete file path to be read.</param>
214 /// <param name="detectEncodingFromByteOrderMarks">Indicates whether to look for byte order marks at the beginning of the file.</param>
215 public void Load(string path, bool detectEncodingFromByteOrderMarks)
217 Load(new StreamReader(path, detectEncodingFromByteOrderMarks));
220 /// <summary>
221 /// Loads a mixed code document from a file.
222 /// </summary>
223 /// <param name="path">The complete file path to be read.</param>
224 /// <param name="encoding">The character encoding to use.</param>
225 public void Load(string path, Encoding encoding)
227 Load(new StreamReader(path, encoding));
230 /// <summary>
231 /// Loads a mixed code document from a file.
232 /// </summary>
233 /// <param name="path">The complete file path to be read.</param>
234 /// <param name="encoding">The character encoding to use.</param>
235 /// <param name="detectEncodingFromByteOrderMarks">Indicates whether to look for byte order marks at the beginning of the file.</param>
236 public void Load(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks)
238 Load(new StreamReader(path, encoding, detectEncodingFromByteOrderMarks));
241 /// <summary>
242 /// Loads a mixed code document from a file.
243 /// </summary>
244 /// <param name="path">The complete file path to be read.</param>
245 /// <param name="encoding">The character encoding to use.</param>
246 /// <param name="detectEncodingFromByteOrderMarks">Indicates whether to look for byte order marks at the beginning of the file.</param>
247 /// <param name="buffersize">The minimum buffer size.</param>
248 public void Load(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int buffersize)
250 Load(new StreamReader(path, encoding, detectEncodingFromByteOrderMarks, buffersize));
253 /// <summary>
254 /// Loads the mixed code document from the specified TextReader.
255 /// </summary>
256 /// <param name="reader">The TextReader used to feed the HTML data into the document.</param>
257 public void Load(TextReader reader)
259 _codefragments.Clear();
260 _textfragments.Clear();
262 // all pseudo constructors get down to this one
263 StreamReader sr = reader as StreamReader;
264 if (sr != null)
266 _streamencoding = sr.CurrentEncoding;
269 _text = reader.ReadToEnd();
270 reader.Close();
271 Parse();
274 /// <summary>
275 /// Loads a mixed document from a text
276 /// </summary>
277 /// <param name="html">The text to load.</param>
278 public void LoadHtml(string html)
280 Load(new StringReader(html));
283 /// <summary>
284 /// Saves the mixed document to the specified stream.
285 /// </summary>
286 /// <param name="outStream">The stream to which you want to save.</param>
287 public void Save(Stream outStream)
289 StreamWriter sw = new StreamWriter(outStream, GetOutEncoding());
290 Save(sw);
293 /// <summary>
294 /// Saves the mixed document to the specified stream.
295 /// </summary>
296 /// <param name="outStream">The stream to which you want to save.</param>
297 /// <param name="encoding">The character encoding to use.</param>
298 public void Save(Stream outStream, Encoding encoding)
300 StreamWriter sw = new StreamWriter(outStream, encoding);
301 Save(sw);
304 /// <summary>
305 /// Saves the mixed document to the specified file.
306 /// </summary>
307 /// <param name="filename">The location of the file where you want to save the document.</param>
308 public void Save(string filename)
310 StreamWriter sw = new StreamWriter(filename, false, GetOutEncoding());
311 Save(sw);
314 /// <summary>
315 /// Saves the mixed document to the specified file.
316 /// </summary>
317 /// <param name="filename">The location of the file where you want to save the document.</param>
318 /// <param name="encoding">The character encoding to use.</param>
319 public void Save(string filename, Encoding encoding)
321 StreamWriter sw = new StreamWriter(filename, false, encoding);
322 Save(sw);
325 /// <summary>
326 /// Saves the mixed document to the specified StreamWriter.
327 /// </summary>
328 /// <param name="writer">The StreamWriter to which you want to save.</param>
329 public void Save(StreamWriter writer)
331 Save((TextWriter) writer);
334 /// <summary>
335 /// Saves the mixed document to the specified TextWriter.
336 /// </summary>
337 /// <param name="writer">The TextWriter to which you want to save.</param>
338 public void Save(TextWriter writer)
340 writer.Flush();
343 #endregion
345 #region Internal Methods
347 internal MixedCodeDocumentFragment CreateFragment(MixedCodeDocumentFragmentType type)
349 switch (type)
351 case MixedCodeDocumentFragmentType.Text:
352 return new MixedCodeDocumentTextFragment(this);
354 case MixedCodeDocumentFragmentType.Code:
355 return new MixedCodeDocumentCodeFragment(this);
357 default:
358 throw new NotSupportedException();
362 internal Encoding GetOutEncoding()
364 if (_streamencoding != null)
365 return _streamencoding;
366 return Encoding.Default;
369 #endregion
371 #region Private Methods
373 private void IncrementPosition()
375 _index++;
376 if (_c == 10)
378 _lineposition = 1;
379 _line++;
381 else
382 _lineposition++;
385 private void Parse()
387 _state = ParseState.Text;
388 _index = 0;
389 _currentfragment = CreateFragment(MixedCodeDocumentFragmentType.Text);
391 while (_index < _text.Length)
393 _c = _text[_index];
394 IncrementPosition();
396 switch (_state)
398 case ParseState.Text:
399 if (_index + TokenCodeStart.Length < _text.Length)
401 if (_text.Substring(_index - 1, TokenCodeStart.Length) == TokenCodeStart)
403 _state = ParseState.Code;
404 _currentfragment.Length = _index - 1 - _currentfragment.Index;
405 _currentfragment = CreateFragment(MixedCodeDocumentFragmentType.Code);
406 SetPosition();
407 continue;
410 break;
412 case ParseState.Code:
413 if (_index + TokenCodeEnd.Length < _text.Length)
415 if (_text.Substring(_index - 1, TokenCodeEnd.Length) == TokenCodeEnd)
417 _state = ParseState.Text;
418 _currentfragment.Length = _index + TokenCodeEnd.Length - _currentfragment.Index;
419 _index += TokenCodeEnd.Length;
420 _lineposition += TokenCodeEnd.Length;
421 _currentfragment = CreateFragment(MixedCodeDocumentFragmentType.Text);
422 SetPosition();
423 continue;
426 break;
430 _currentfragment.Length = _index - _currentfragment.Index;
433 private void SetPosition()
435 _currentfragment.Line = _line;
436 _currentfragment._lineposition = _lineposition;
437 _currentfragment.Index = _index - 1;
438 _currentfragment.Length = 0;
441 #endregion
443 #region Nested type: ParseState
445 private enum ParseState
447 Text,
448 Code
451 #endregion