Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / System.XML / System.Xml / XmlIteratorNodeList.cs
1 //
2 // System.Xml.XmlIteratorNodeList
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // (C) 2006 Novell Inc.
8 //
9
10 //
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:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
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.
29 //
30
31 using System;
32 using System.Collections;
33 using System.Xml.XPath;
34
35 namespace System.Xml
36 {
37         internal class XmlIteratorNodeList : XmlNodeList//, IDisposable
38         {
39                 //XmlDocument doc;
40                 XPathNodeIterator source;
41                 XPathNodeIterator iterator;
42                 ArrayList list;
43                 bool finished;
44
45                 #region Constructors
46
47                 public XmlIteratorNodeList (XmlDocument doc, XPathNodeIterator iter)
48                 {
49                         if (doc == null)
50                                 throw new Exception ("huh?");
51                         //this.doc = doc;
52                         //doc.NodeRemoving += SaveNodeList;
53                         source = iter;
54                         iterator = iter.Clone ();
55                         list = new ArrayList ();
56                 }
57
58                 #endregion
59
60                 #region Properties
61
62                 public override int Count {
63                         get {
64 /*
65                                 // The performance on Count depends on the 
66                                 // iterator which is actually used. In some
67                                 // iterators, getting iterator.Count is much
68                                 // faster.
69
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
74                                 // performance.
75                                 
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.
81
82                                 if (!finished) {
83                                         BaseIterator iter = iterator as BaseIterator;
84                                         if (iter != null && iter.ReverseAxis || iter is SlashIterator)
85                                                 return iter.Count;
86
87                                         while (iterator.MoveNext ())
88                                                 list.Add (((IHasXmlNode) iterator.Current).GetNode ());
89                                         finished = true;
90                                 }
91                                 return list.Count;
92 */
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;
98                         }
99                 }
100
101                 #endregion
102
103                 #region Methods
104
105                 /*
106                 void IDisposable.Dispose ()
107                 {
108                         if (!event_detached) {
109                                 event_detached = true;
110                                 doc.NodeRemoving -= SaveNodeList;
111                         }
112                 }
113
114                 void SaveNodeList (object o, XmlNodeChangedEventArgs e)
115                 {
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;
120                 }
121                 */
122
123                 public override IEnumerator GetEnumerator ()
124                 {
125                         if (finished)
126                                 return list.GetEnumerator ();
127                         else
128                                 return new XPathNodeIteratorNodeListIterator (source);
129                                 //return new XPathNodeIteratorNodeListIterator2 (this);
130                 }
131
132                 public override XmlNode Item (int index)
133                 {
134                         if (index < 0)
135                                 return null;
136                         if (index < list.Count)
137                                 return (XmlNode) list [index];
138                         index++;
139                         while (iterator.CurrentPosition < index) {
140                                 if (!iterator.MoveNext ()) {
141                                         finished = true;
142                                         return null;
143                                 }
144                                 list.Add (((IHasXmlNode) iterator.Current).GetNode ());
145                         }
146                         return (XmlNode) list [index - 1];
147                 }
148
149                 #endregion
150
151                 // FIXME: switch to XPathNodeIteratorNodeListIterator2.
152                 class XPathNodeIteratorNodeListIterator : IEnumerator
153                 {
154                         XPathNodeIterator iter;
155                         XPathNodeIterator source;
156                         public XPathNodeIteratorNodeListIterator (XPathNodeIterator source)
157                         {
158                                 this.source = source;
159                                 Reset ();
160                         }
161
162                         public bool MoveNext ()
163                         {
164                                 return iter.MoveNext ();
165                         }
166
167                         public object Current {
168                                 get { return ((IHasXmlNode) iter.Current).GetNode (); }
169                         }
170
171                         public void Reset ()
172                         {
173                                 iter = source.Clone ();
174                         }
175                 }
176
177                 /*
178                 class XPathNodeIteratorNodeListIterator2 : IEnumerator
179                 {
180                         int current = -1;
181                         XmlIteratorNodeList source;
182
183                         public XPathNodeIteratorNodeListIterator2 (XmlIteratorNodeList source)
184                         {
185                                 this.source = source;
186                         }
187
188                         public bool MoveNext ()
189                         {
190                                 return source [++current] != null;
191                         }
192
193                         public object Current {
194                                 get { return source [current]; }
195                         }
196
197                         public void Reset ()
198                         {
199                                 current = -1;
200                         }
201                 }
202                 */
203         }
204 }