2 // System.Xml.XmlIteratorNodeList
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // (C) 2006 Novell Inc.
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections;
33 using System.Xml.XPath;
37 internal class XmlIteratorNodeList : XmlNodeList//, IDisposable
40 XPathNodeIterator source;
41 XPathNodeIterator iterator;
47 public XmlIteratorNodeList (XmlDocument doc, XPathNodeIterator iter)
50 throw new Exception ("huh?");
52 //doc.NodeRemoving += SaveNodeList;
54 iterator = iter.Clone ();
55 list = new ArrayList ();
62 public override int Count {
65 // The performance on Count depends on the
66 // iterator which is actually used. In some
67 // iterators, getting iterator.Count is much
70 // With (current) implementation in general,
71 // those iterators that requires sorting is
72 // likely to have already-computed arrays, so
73 // for them getting Count does not impact on
76 // But by default, getting iterator.Count means
77 // it internally iterates all the nodes. That
78 // might result in duplicate iteration (so
79 // ineffective). So here I decided that it
80 // just collects all the nodes to the list.
83 BaseIterator iter = iterator as BaseIterator;
84 if (iter != null && iter.ReverseAxis || iter is SlashIterator)
87 while (iterator.MoveNext ())
88 list.Add (((IHasXmlNode) iterator.Current).GetNode ());
93 // anyways such code that uses
94 // XmlNodeList.Count already gives up
95 // performance. Also, storing things in the
96 // list causes extra memory consumption.
97 return iterator.Count;
106 void IDisposable.Dispose ()
108 if (!event_detached) {
109 event_detached = true;
110 doc.NodeRemoving -= SaveNodeList;
114 void SaveNodeList (object o, XmlNodeChangedEventArgs e)
116 if (Item (Count) != null || !finished)
117 throw new Exception (); // dummy. It accesses to the end of the list
118 doc.NodeRemoving -= SaveNodeList;
119 event_detached = true;
123 public override IEnumerator GetEnumerator ()
126 return list.GetEnumerator ();
128 return new XPathNodeIteratorNodeListIterator (source);
129 //return new XPathNodeIteratorNodeListIterator2 (this);
132 public override XmlNode Item (int index)
136 if (index < list.Count)
137 return (XmlNode) list [index];
139 while (iterator.CurrentPosition < index) {
140 if (!iterator.MoveNext ()) {
144 list.Add (((IHasXmlNode) iterator.Current).GetNode ());
146 return (XmlNode) list [index - 1];
151 // FIXME: switch to XPathNodeIteratorNodeListIterator2.
152 class XPathNodeIteratorNodeListIterator : IEnumerator
154 XPathNodeIterator iter;
155 XPathNodeIterator source;
156 public XPathNodeIteratorNodeListIterator (XPathNodeIterator source)
158 this.source = source;
162 public bool MoveNext ()
164 return iter.MoveNext ();
167 public object Current {
168 get { return ((IHasXmlNode) iter.Current).GetNode (); }
173 iter = source.Clone ();
178 class XPathNodeIteratorNodeListIterator2 : IEnumerator
181 XmlIteratorNodeList source;
183 public XPathNodeIteratorNodeListIterator2 (XmlIteratorNodeList source)
185 this.source = source;
188 public bool MoveNext ()
190 return source [++current] != null;
193 public object Current {
194 get { return source [current]; }