[sgen] Don't consider managed write barriers to be critical methods.
[mono-project.git] / docs / HtmlAgilityPack / HtmlNodeCollection.cs
blob379e37082d72f926931e3ca5b380ec0fd847ae58
1 // HtmlAgilityPack V1.0 - Simon Mourier <simon underscore mourier at hotmail dot com>
2 using System;
3 using System.Collections;
4 using System.Collections.Generic;
6 namespace HtmlAgilityPack
8 /// <summary>
9 /// Represents a combined list and collection of HTML nodes.
10 /// </summary>
11 public class HtmlNodeCollection : IList<HtmlNode>
13 #region Fields
15 private readonly HtmlNode _parentnode;
16 private readonly List<HtmlNode> _items = new List<HtmlNode>();
18 #endregion
20 #region Constructors
22 /// <summary>
23 /// Initialize the HtmlNodeCollection with the base parent node
24 /// </summary>
25 /// <param name="parentnode">The base node of the collection</param>
26 public HtmlNodeCollection(HtmlNode parentnode)
28 _parentnode = parentnode; // may be null
31 #endregion
33 #region Properties
35 /// <summary>
36 /// Gets a given node from the list.
37 /// </summary>
38 public int this[HtmlNode node]
40 get
42 int index = GetNodeIndex(node);
43 if (index == -1)
45 throw new ArgumentOutOfRangeException("node",
46 "Node \"" + node.CloneNode(false).OuterHtml +
47 "\" was not found in the collection");
49 return index;
53 /// <summary>
54 /// Get node with tag name
55 /// </summary>
56 /// <param name="nodeName"></param>
57 /// <returns></returns>
58 public HtmlNode this[string nodeName]
60 get
62 nodeName = nodeName.ToLower();
63 for (int i = 0; i < _items.Count; i++)
64 if (_items[i].Equals(nodeName))
65 return _items[i];
67 return null;
71 #endregion
73 #region IList<HtmlNode> Members
75 /// <summary>
76 /// Gets the number of elements actually contained in the list.
77 /// </summary>
78 public int Count
80 get { return _items.Count; }
83 /// <summary>
84 /// Is collection read only
85 /// </summary>
86 public bool IsReadOnly
88 get { return false; }
91 /// <summary>
92 /// Gets the node at the specified index.
93 /// </summary>
94 public HtmlNode this[int index]
96 get { return _items[index]; }
97 set { _items[index] = value; }
100 /// <summary>
101 /// Add node to the collection
102 /// </summary>
103 /// <param name="node"></param>
104 public void Add(HtmlNode node)
106 _items.Add(node);
109 /// <summary>
110 /// Clears out the collection of HtmlNodes. Removes each nodes reference to parentnode, nextnode and prevnode
111 /// </summary>
112 public void Clear()
114 foreach (HtmlNode node in _items)
116 node.ParentNode = null;
117 node.NextSibling = null;
118 node.PreviousSibling = null;
120 _items.Clear();
123 /// <summary>
124 /// Gets existence of node in collection
125 /// </summary>
126 /// <param name="item"></param>
127 /// <returns></returns>
128 public bool Contains(HtmlNode item)
130 return _items.Contains(item);
133 /// <summary>
134 /// Copy collection to array
135 /// </summary>
136 /// <param name="array"></param>
137 /// <param name="arrayIndex"></param>
138 public void CopyTo(HtmlNode[] array, int arrayIndex)
140 _items.CopyTo(array, arrayIndex);
143 /// <summary>
144 /// Get Enumerator
145 /// </summary>
146 /// <returns></returns>
147 IEnumerator<HtmlNode> IEnumerable<HtmlNode>.GetEnumerator()
149 return _items.GetEnumerator();
152 /// <summary>
153 /// Get Explicit Enumerator
154 /// </summary>
155 /// <returns></returns>
156 IEnumerator IEnumerable.GetEnumerator()
158 return _items.GetEnumerator();
161 /// <summary>
162 /// Get index of node
163 /// </summary>
164 /// <param name="item"></param>
165 /// <returns></returns>
166 public int IndexOf(HtmlNode item)
168 return _items.IndexOf(item);
171 /// <summary>
172 /// Insert node at index
173 /// </summary>
174 /// <param name="index"></param>
175 /// <param name="node"></param>
176 public void Insert(int index, HtmlNode node)
178 HtmlNode next = null;
179 HtmlNode prev = null;
181 if (index > 0)
183 prev = _items[index - 1];
186 if (index < _items.Count)
188 next = _items[index];
191 _items.Insert(index, node);
193 if (prev != null)
195 if (node == prev)
197 throw new InvalidProgramException("Unexpected error.");
199 prev._nextnode = node;
202 if (next != null)
204 next._prevnode = node;
207 node._prevnode = prev;
208 if (next == node)
210 throw new InvalidProgramException("Unexpected error.");
212 node._nextnode = next;
213 node._parentnode = _parentnode;
216 /// <summary>
217 /// Remove node
218 /// </summary>
219 /// <param name="item"></param>
220 /// <returns></returns>
221 public bool Remove(HtmlNode item)
223 int i = _items.IndexOf(item);
224 RemoveAt(i);
225 return true;
228 /// <summary>
229 /// Remove <see cref="HtmlNode"/> at index
230 /// </summary>
231 /// <param name="index"></param>
232 public void RemoveAt(int index)
234 HtmlNode next = null;
235 HtmlNode prev = null;
236 HtmlNode oldnode = _items[index];
238 if (index > 0)
240 prev = _items[index - 1];
243 if (index < (_items.Count - 1))
245 next = _items[index + 1];
248 _items.RemoveAt(index);
250 if (prev != null)
252 if (next == prev)
254 throw new InvalidProgramException("Unexpected error.");
256 prev._nextnode = next;
259 if (next != null)
261 next._prevnode = prev;
264 oldnode._prevnode = null;
265 oldnode._nextnode = null;
266 oldnode._parentnode = null;
269 #endregion
271 #region Public Methods
273 /// <summary>
274 /// Get first instance of node in supplied collection
275 /// </summary>
276 /// <param name="items"></param>
277 /// <param name="name"></param>
278 /// <returns></returns>
279 public static HtmlNode FindFirst(HtmlNodeCollection items, string name)
281 foreach (HtmlNode node in items)
283 if (node.Name.ToLower().Contains(name))
284 return node;
285 if (node.HasChildNodes)
287 HtmlNode returnNode = FindFirst(node.ChildNodes, name);
288 if (returnNode != null)
289 return returnNode;
292 return null;
295 /// <summary>
296 /// Add node to the end of the collection
297 /// </summary>
298 /// <param name="node"></param>
299 public void Append(HtmlNode node)
301 HtmlNode last = null;
302 if (_items.Count > 0)
304 last = _items[_items.Count - 1];
307 _items.Add(node);
308 node._prevnode = last;
309 node._nextnode = null;
310 node._parentnode = _parentnode;
311 if (last != null)
313 if (last == node)
315 throw new InvalidProgramException("Unexpected error.");
317 last._nextnode = node;
321 /// <summary>
322 /// Get first instance of node with name
323 /// </summary>
324 /// <param name="name"></param>
325 /// <returns></returns>
326 public HtmlNode FindFirst(string name)
328 return FindFirst(this, name);
331 /// <summary>
332 /// Get index of node
333 /// </summary>
334 /// <param name="node"></param>
335 /// <returns></returns>
336 public int GetNodeIndex(HtmlNode node)
338 // TODO: should we rewrite this? what would be the key of a node?
339 for (int i = 0; i < _items.Count; i++)
341 if (node == (_items[i]))
343 return i;
346 return -1;
349 /// <summary>
350 /// Add node to the beginning of the collection
351 /// </summary>
352 /// <param name="node"></param>
353 public void Prepend(HtmlNode node)
355 HtmlNode first = null;
356 if (_items.Count > 0)
358 first = _items[0];
361 _items.Insert(0, node);
363 if (node == first)
365 throw new InvalidProgramException("Unexpected error.");
367 node._nextnode = first;
368 node._prevnode = null;
369 node._parentnode = _parentnode;
370 if (first != null)
372 first._prevnode = node;
376 /// <summary>
377 /// Remove node at index
378 /// </summary>
379 /// <param name="index"></param>
380 /// <returns></returns>
381 public bool Remove(int index)
383 RemoveAt(index);
384 return true;
387 /// <summary>
388 /// Replace node at index
389 /// </summary>
390 /// <param name="index"></param>
391 /// <param name="node"></param>
392 public void Replace(int index, HtmlNode node)
394 HtmlNode next = null;
395 HtmlNode prev = null;
396 HtmlNode oldnode = _items[index];
398 if (index > 0)
400 prev = _items[index - 1];
403 if (index < (_items.Count - 1))
405 next = _items[index + 1];
408 _items[index] = node;
410 if (prev != null)
412 if (node == prev)
414 throw new InvalidProgramException("Unexpected error.");
416 prev._nextnode = node;
419 if (next != null)
421 next._prevnode = node;
424 node._prevnode = prev;
426 if (next == node)
428 throw new InvalidProgramException("Unexpected error.");
431 node._nextnode = next;
432 node._parentnode = _parentnode;
434 oldnode._prevnode = null;
435 oldnode._nextnode = null;
436 oldnode._parentnode = null;
439 #endregion
441 #region LINQ Methods
443 /// <summary>
444 /// Get all node descended from this collection
445 /// </summary>
446 /// <returns></returns>
447 public IEnumerable<HtmlNode> DescendantNodes()
449 foreach (HtmlNode item in _items)
450 foreach (HtmlNode n in item.DescendantNodes())
451 yield return n;
454 /// <summary>
455 /// Get all node descended from this collection
456 /// </summary>
457 /// <returns></returns>
458 public IEnumerable<HtmlNode> Descendants()
460 foreach (HtmlNode item in _items)
461 foreach (HtmlNode n in item.Descendants())
462 yield return n;
465 /// <summary>
466 /// Get all node descended from this collection with matching name
467 /// </summary>
468 /// <returns></returns>
469 public IEnumerable<HtmlNode> Descendants(string name)
471 foreach (HtmlNode item in _items)
472 foreach (HtmlNode n in item.Descendants(name))
473 yield return n;
476 /// <summary>
477 /// Gets all first generation elements in collection
478 /// </summary>
479 /// <returns></returns>
480 public IEnumerable<HtmlNode> Elements()
482 foreach (HtmlNode item in _items)
483 foreach (HtmlNode n in item.ChildNodes)
484 yield return n;
487 /// <summary>
488 /// Gets all first generation elements matching name
489 /// </summary>
490 /// <param name="name"></param>
491 /// <returns></returns>
492 public IEnumerable<HtmlNode> Elements(string name)
494 foreach (HtmlNode item in _items)
495 foreach (HtmlNode n in item.Elements(name))
496 yield return n;
499 /// <summary>
500 /// All first generation nodes in collection
501 /// </summary>
502 /// <returns></returns>
503 public IEnumerable<HtmlNode> Nodes()
505 foreach (HtmlNode item in _items)
506 foreach (HtmlNode n in item.ChildNodes)
507 yield return n;
510 #endregion