Iterator.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239
  1. //
  2. // System.Xml.XPath.BaseIterator
  3. //
  4. // Author:
  5. // Piers Haken ([email protected])
  6. // Atsushi Enomoto ([email protected])
  7. //
  8. // (C) 2002 Piers Haken
  9. // (C) 2003 Atsushi Enomoto
  10. //
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. using System;
  32. using System.Collections;
  33. using System.Xml;
  34. using System.Xml.XPath;
  35. using System.Xml.Xsl;
  36. #if NET_2_0
  37. using NSResolver = System.Xml.IXmlNamespaceResolver;
  38. #else
  39. using NSResolver = System.Xml.XmlNamespaceManager;
  40. #endif
  41. namespace System.Xml.XPath
  42. {
  43. internal abstract class BaseIterator : XPathNodeIterator
  44. {
  45. private NSResolver _nsm;
  46. protected bool _needClone = true; // TODO: use this field in practice.
  47. internal BaseIterator (BaseIterator other)
  48. {
  49. _nsm = other._nsm;
  50. }
  51. internal BaseIterator (NSResolver nsm)
  52. {
  53. _nsm = nsm;
  54. }
  55. public NSResolver NamespaceManager
  56. {
  57. get { return _nsm; }
  58. set { _nsm = value; }
  59. }
  60. public virtual bool ReverseAxis {
  61. get { return false; }
  62. }
  63. public abstract bool RequireSorting { get; }
  64. public virtual int ComparablePosition {
  65. get {
  66. if (ReverseAxis) {
  67. int diff = Count - CurrentPosition + 1;
  68. return diff < 1 ? 1 : diff;
  69. }
  70. else
  71. return CurrentPosition;
  72. }
  73. }
  74. public override string ToString ()
  75. {
  76. if (Current != null)
  77. return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
  78. else
  79. return this.GetType().ToString () + "[" + CurrentPosition + "]";
  80. }
  81. }
  82. internal class WrapperIterator : BaseIterator
  83. {
  84. XPathNodeIterator iter;
  85. public WrapperIterator (XPathNodeIterator iter, NSResolver nsm)
  86. : base (nsm)
  87. {
  88. this.iter = iter;
  89. }
  90. public override XPathNodeIterator Clone ()
  91. {
  92. return new WrapperIterator (iter.Clone (), NamespaceManager);
  93. }
  94. public override bool MoveNext ()
  95. {
  96. return iter.MoveNext ();
  97. }
  98. public override XPathNavigator Current {
  99. get { return iter.Current; }
  100. }
  101. public override int CurrentPosition {
  102. get { return iter.CurrentPosition; }
  103. }
  104. public override bool RequireSorting {
  105. get { return true; }
  106. }
  107. }
  108. internal abstract class SimpleIterator : BaseIterator
  109. {
  110. protected readonly BaseIterator _iter;
  111. protected readonly XPathNavigator _nav;
  112. protected XPathNavigator _current;
  113. protected int _pos;
  114. public SimpleIterator (BaseIterator iter) : base (iter)
  115. {
  116. _iter = iter;
  117. _nav = iter.Current.Clone ();
  118. _current = _nav.Clone ();
  119. }
  120. protected SimpleIterator (SimpleIterator other) : base (other)
  121. {
  122. if (other._nav == null)
  123. _iter = (BaseIterator) other._iter.Clone ();
  124. else
  125. _nav = other._nav.Clone ();
  126. _pos = other._pos;
  127. _current = other._current.Clone ();
  128. }
  129. public SimpleIterator (XPathNavigator nav, NSResolver nsm) : base (nsm)
  130. {
  131. _nav = nav.Clone ();
  132. _current = nav.Clone ();
  133. }
  134. public override XPathNavigator Current { get { return _current; }}
  135. public override int CurrentPosition { get { return _pos; }}
  136. }
  137. internal class SelfIterator : SimpleIterator
  138. {
  139. public SelfIterator (BaseIterator iter) : base (iter) {}
  140. public SelfIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
  141. protected SelfIterator (SelfIterator other) : base (other) {}
  142. public override XPathNodeIterator Clone () { return new SelfIterator (this); }
  143. public override bool MoveNext ()
  144. {
  145. if (_pos == 0)
  146. {
  147. _pos = 1;
  148. _current = _needClone ? _nav.Clone () : _nav;
  149. return true;
  150. }
  151. return false;
  152. }
  153. public override bool RequireSorting { get { return false; } }
  154. }
  155. internal class NullIterator : SelfIterator
  156. {
  157. public NullIterator (BaseIterator iter) : base (iter) {}
  158. public NullIterator (XPathNavigator nav) : this (nav, null) {}
  159. public NullIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
  160. protected NullIterator (NullIterator other) : base (other) {}
  161. public override XPathNodeIterator Clone () { return new NullIterator (this); }
  162. public override bool MoveNext ()
  163. {
  164. return false;
  165. }
  166. }
  167. internal class ParensIterator : BaseIterator
  168. {
  169. BaseIterator _iter;
  170. public ParensIterator (BaseIterator iter) : base (iter)
  171. {
  172. _iter = iter;
  173. }
  174. protected ParensIterator (ParensIterator other) : base (other)
  175. {
  176. _iter = (BaseIterator) other._iter.Clone ();
  177. }
  178. public override XPathNodeIterator Clone () { return new ParensIterator (this); }
  179. public override bool MoveNext ()
  180. {
  181. return _iter.MoveNext ();
  182. }
  183. public override XPathNavigator Current { get { return _iter.Current; }}
  184. public override int CurrentPosition { get { return _iter.CurrentPosition; } }
  185. public override bool RequireSorting { get { return _iter.RequireSorting; } }
  186. public override int Count { get { return _iter.Count; } }
  187. }
  188. internal class ParentIterator : SimpleIterator
  189. {
  190. public ParentIterator (BaseIterator iter) : base (iter) {}
  191. protected ParentIterator (ParentIterator other) : base (other) {}
  192. public ParentIterator (XPathNavigator nav, NSResolver nsm) : base (nav, nsm) {}
  193. public override XPathNodeIterator Clone () { return new ParentIterator (this); }
  194. public override bool MoveNext ()
  195. {
  196. if (_pos == 0 && _nav.MoveToParent ())
  197. {
  198. _pos = 1;
  199. _current = _needClone ? _nav.Clone () : _nav;
  200. return true;
  201. }
  202. return false;
  203. }
  204. public override bool ReverseAxis { get { return true; } }
  205. public override bool RequireSorting { get { return true; } }
  206. }
  207. internal class ChildIterator : SimpleIterator
  208. {
  209. public ChildIterator (BaseIterator iter) : base (iter) {}
  210. protected ChildIterator (ChildIterator other) : base (other) {}
  211. public override XPathNodeIterator Clone () { return new ChildIterator (this); }
  212. public override bool MoveNext ()
  213. {
  214. bool fSuccess = (_pos == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
  215. if (fSuccess) {
  216. _pos ++;
  217. // This clone cannot be omitted
  218. _current = _nav.Clone ();
  219. }
  220. return fSuccess;
  221. }
  222. public override bool RequireSorting { get { return false; } }
  223. }
  224. internal class FollowingSiblingIterator : SimpleIterator
  225. {
  226. public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
  227. protected FollowingSiblingIterator (FollowingSiblingIterator other) : base (other) {}
  228. public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
  229. public override bool MoveNext ()
  230. {
  231. switch (_nav.NodeType) {
  232. case XPathNodeType.Attribute:
  233. case XPathNodeType.Namespace:
  234. // They have no siblings.
  235. return false;
  236. }
  237. if (_nav.MoveToNext ())
  238. {
  239. _pos ++;
  240. // This clone cannot be omitted
  241. _current = _nav.Clone ();
  242. return true;
  243. }
  244. return false;
  245. }
  246. public override bool RequireSorting { get { return false; } }
  247. }
  248. internal class PrecedingSiblingIterator : SimpleIterator
  249. {
  250. bool finished;
  251. bool started;
  252. XPathNavigator startPosition;
  253. public PrecedingSiblingIterator (BaseIterator iter) : base (iter)
  254. {
  255. startPosition = iter.Current.Clone ();
  256. _current = startPosition.Clone ();
  257. }
  258. protected PrecedingSiblingIterator (PrecedingSiblingIterator other) : base (other)
  259. {
  260. startPosition = other.startPosition;
  261. started = other.started;
  262. finished = other.finished;
  263. _current = other._current.Clone ();
  264. }
  265. public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
  266. public override bool MoveNext ()
  267. {
  268. if (finished)
  269. return false;
  270. if (!started) {
  271. started = true;
  272. switch (_nav.NodeType) {
  273. case XPathNodeType.Attribute:
  274. case XPathNodeType.Namespace:
  275. // They have no siblings.
  276. finished = true;
  277. return false;
  278. }
  279. _nav.MoveToFirst ();
  280. if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Same) {
  281. _pos++;
  282. // This clone cannot be omitted
  283. _current = _nav.Clone ();
  284. return true;
  285. }
  286. } else {
  287. if (!_nav.MoveToNext ()) {
  288. finished = true;
  289. return false;
  290. }
  291. }
  292. if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
  293. // Note that if _nav contains only 1 node, it won't be Same.
  294. finished = true;
  295. return false;
  296. } else {
  297. _pos ++;
  298. // This clone cannot be omitted
  299. _current = _nav.Clone ();
  300. return true;
  301. }
  302. }
  303. public override bool ReverseAxis {
  304. get { return true; }
  305. }
  306. public override bool RequireSorting { get { return true; } }
  307. }
  308. internal class AncestorIterator : SimpleIterator
  309. {
  310. bool finished;
  311. bool started;
  312. ArrayList positions = new ArrayList ();
  313. XPathNavigator startPosition;
  314. int nextDepth;
  315. public AncestorIterator (BaseIterator iter) : base (iter)
  316. {
  317. startPosition = iter.Current.Clone ();
  318. _current = startPosition.Clone ();
  319. }
  320. protected AncestorIterator (AncestorIterator other) : base (other)
  321. {
  322. startPosition = other.startPosition;
  323. started = other.started;
  324. finished = other.finished;
  325. positions = (ArrayList) other.positions.Clone ();
  326. nextDepth = other.nextDepth;
  327. _current = other._current.Clone ();
  328. }
  329. public override XPathNodeIterator Clone () { return new AncestorIterator (this); }
  330. public override bool MoveNext ()
  331. {
  332. if (finished)
  333. return false;
  334. if (!started) {
  335. started = true;
  336. // This clone cannot be omitted
  337. XPathNavigator ancestors = startPosition.Clone ();
  338. ancestors.MoveToParent ();
  339. _nav.MoveToParent ();
  340. while (ancestors.NodeType != XPathNodeType.Root) {
  341. int i = 0;
  342. _nav.MoveToFirst ();
  343. while (_nav.ComparePosition (ancestors) == XmlNodeOrder.Before) {
  344. _nav.MoveToNext ();
  345. i++;
  346. }
  347. positions.Add (i);
  348. if (!ancestors.MoveToParent ())
  349. break; // It is for detached nodes under XmlDocumentNavigator
  350. _nav.MoveToParent ();
  351. }
  352. positions.Reverse ();
  353. if (startPosition.NodeType != XPathNodeType.Root) {
  354. // First time it returns Root
  355. _pos++;
  356. // This clone cannot be omitted
  357. _current = _nav.Clone ();
  358. return true;
  359. }
  360. }
  361. // Don't worry about node type of start position, like AncestorOrSelf.
  362. // It should be Element or Root.
  363. if (nextDepth < positions.Count) {
  364. int thisTimePos = (int) positions [nextDepth];
  365. _nav.MoveToFirstChild ();
  366. for (int i = 0; i < thisTimePos; i++)
  367. _nav.MoveToNext ();
  368. nextDepth++;
  369. _pos++;
  370. // This clone cannot be omitted
  371. _current = _nav.Clone ();
  372. return true;
  373. }
  374. finished = true;
  375. return false;
  376. }
  377. public override bool ReverseAxis {
  378. get { return true; }
  379. }
  380. public override bool RequireSorting { get { return true; } }
  381. public override int Count { get { return positions.Count; } }
  382. }
  383. internal class AncestorOrSelfIterator : SimpleIterator
  384. {
  385. bool finished;
  386. bool started;
  387. ArrayList positions = new ArrayList ();
  388. XPathNavigator startPosition;
  389. int nextDepth;
  390. public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
  391. {
  392. startPosition = iter.Current.Clone ();
  393. _current = startPosition.Clone ();
  394. }
  395. protected AncestorOrSelfIterator (AncestorOrSelfIterator other) : base (other)
  396. {
  397. startPosition = other.startPosition;
  398. started = other.started;
  399. finished = other.finished;
  400. positions = (ArrayList) other.positions.Clone ();
  401. nextDepth = other.nextDepth;
  402. _current = other._current.Clone ();
  403. }
  404. public override XPathNodeIterator Clone () { return new AncestorOrSelfIterator (this); }
  405. public override bool MoveNext ()
  406. {
  407. bool initialIteration = false;
  408. if (finished)
  409. return false;
  410. if (!started) {
  411. initialIteration = true;
  412. started = true;
  413. // This clone cannot be omitted
  414. XPathNavigator ancestors = startPosition.Clone ();
  415. do {
  416. int i = 0;
  417. _nav.MoveToFirst ();
  418. while (_nav.ComparePosition (ancestors) == XmlNodeOrder.Before) {
  419. _nav.MoveToNext ();
  420. i++;
  421. }
  422. positions.Add (i);
  423. if (!ancestors.MoveToParent ())
  424. break; // for detached nodes under XmlDocumentNavigator.
  425. _nav.MoveToParent ();
  426. } while (ancestors.NodeType != XPathNodeType.Root);
  427. positions.Reverse ();
  428. }
  429. if (initialIteration && startPosition.NodeType != XPathNodeType.Root) {
  430. // This clone cannot be omitted
  431. _current = _nav.Clone ();
  432. return true;
  433. } else if (nextDepth + 1 == positions.Count) {
  434. nextDepth++;
  435. _pos++;
  436. _nav.MoveTo (startPosition);
  437. // This clone cannot be omitted
  438. _current = _nav.Clone ();
  439. return true;
  440. }
  441. else if (nextDepth < positions.Count) {
  442. int thisTimePos = (int) positions [nextDepth];
  443. _nav.MoveToFirstChild ();
  444. for (int i = 0; i < thisTimePos; i++)
  445. _nav.MoveToNext ();
  446. nextDepth++;
  447. _pos++;
  448. // This clone cannot be omitted
  449. _current = _nav.Clone ();
  450. return true;
  451. }
  452. finished = true;
  453. return false;
  454. }
  455. public override bool ReverseAxis {
  456. get { return true; }
  457. }
  458. public override bool RequireSorting { get { return true; } }
  459. public override int Count { get { return positions.Count; } }
  460. }
  461. internal class DescendantIterator : SimpleIterator
  462. {
  463. protected int _depth;
  464. private bool _finished;
  465. public DescendantIterator (BaseIterator iter) : base (iter) {}
  466. protected DescendantIterator (DescendantIterator other) : base (other)
  467. {
  468. _depth = other._depth;
  469. _finished = other._finished;
  470. _current = other._current.Clone ();
  471. }
  472. public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
  473. public override bool MoveNext ()
  474. {
  475. if (_finished)
  476. return false;
  477. if (_nav.MoveToFirstChild ())
  478. {
  479. _depth ++;
  480. _pos ++;
  481. // This clone cannot be omitted
  482. _current = _nav.Clone ();
  483. return true;
  484. }
  485. while (_depth != 0)
  486. {
  487. if (_nav.MoveToNext ())
  488. {
  489. _pos ++;
  490. // This clone cannot be omitted
  491. _current = _nav.Clone ();
  492. return true;
  493. }
  494. if (!_nav.MoveToParent ()) // should NEVER fail!
  495. throw new XPathException ("There seems some bugs on the XPathNavigator implementation class.");
  496. _depth --;
  497. }
  498. _finished = true;
  499. return false;
  500. }
  501. public override bool RequireSorting { get { return false; } }
  502. }
  503. internal class DescendantOrSelfIterator : SimpleIterator
  504. {
  505. protected int _depth;
  506. private bool _finished;
  507. public DescendantOrSelfIterator (BaseIterator iter) : base (iter) {}
  508. protected DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other)
  509. {
  510. _depth = other._depth;
  511. _current = other._current.Clone ();
  512. }
  513. public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
  514. public override bool MoveNext ()
  515. {
  516. if (_finished)
  517. return false;
  518. if (_pos == 0)
  519. {
  520. // self
  521. _pos ++;
  522. // This clone cannot be omitted
  523. _current = _nav.Clone ();
  524. return true;
  525. }
  526. if (_nav.MoveToFirstChild ())
  527. {
  528. _depth ++;
  529. _pos ++;
  530. // This clone cannot be omitted
  531. _current = _nav.Clone ();
  532. return true;
  533. }
  534. while (_depth != 0)
  535. {
  536. if (_nav.MoveToNext ())
  537. {
  538. _pos ++;
  539. // This clone cannot be omitted
  540. _current = _nav.Clone ();
  541. return true;
  542. }
  543. if (!_nav.MoveToParent ()) // should NEVER fail!
  544. throw new XPathException ("There seems some bugs on the XPathNavigator implementation class.");
  545. _depth --;
  546. }
  547. _finished = true;
  548. return false;
  549. }
  550. public override bool RequireSorting { get { return false; } }
  551. }
  552. internal class FollowingIterator : SimpleIterator
  553. {
  554. private bool _finished = false;
  555. public FollowingIterator (BaseIterator iter) : base (iter) {}
  556. protected FollowingIterator (FollowingIterator other) : base (other) {}
  557. public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
  558. public override bool MoveNext ()
  559. {
  560. if (_finished)
  561. return false;
  562. if (_pos == 0)
  563. {
  564. if (_nav.MoveToNext ())
  565. {
  566. _pos ++;
  567. // This clone cannot be omitted
  568. _current = _nav.Clone ();
  569. return true;
  570. } else {
  571. while (_nav.MoveToParent ()) {
  572. if (_nav.MoveToNext ()) {
  573. _pos ++;
  574. // This clone cannot be omitted
  575. _current = _nav.Clone ();
  576. return true;
  577. }
  578. }
  579. }
  580. }
  581. else
  582. {
  583. if (_nav.MoveToFirstChild ())
  584. {
  585. _pos ++;
  586. // This clone cannot be omitted
  587. _current = _nav.Clone ();
  588. return true;
  589. }
  590. do
  591. {
  592. if (_nav.MoveToNext ())
  593. {
  594. _pos ++;
  595. // This clone cannot be omitted
  596. _current = _nav.Clone ();
  597. return true;
  598. }
  599. }
  600. while (_nav.MoveToParent ());
  601. }
  602. _finished = true;
  603. return false;
  604. }
  605. public override bool RequireSorting { get { return false; } }
  606. }
  607. internal class PrecedingIterator : SimpleIterator
  608. {
  609. bool finished;
  610. bool started;
  611. XPathNavigator startPosition;
  612. public PrecedingIterator (BaseIterator iter) : base (iter)
  613. {
  614. startPosition = iter.Current.Clone ();
  615. _current = startPosition.Clone ();
  616. }
  617. protected PrecedingIterator (PrecedingIterator other) : base (other)
  618. {
  619. startPosition = other.startPosition;
  620. started = other.started;
  621. finished = other.finished;
  622. _current = other._current.Clone ();
  623. }
  624. public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
  625. public override bool MoveNext ()
  626. {
  627. if (finished)
  628. return false;
  629. if (!started) {
  630. started = true;
  631. _nav.MoveToRoot ();
  632. }
  633. bool loop = true;
  634. while (loop) {
  635. while (!_nav.MoveToFirstChild ()) {
  636. while (!_nav.MoveToNext ()) {
  637. if (!_nav.MoveToParent ()) { // Should not finish, at least before startPosition.
  638. finished = true;
  639. return false;
  640. }
  641. }
  642. break;
  643. }
  644. if (_nav.IsDescendant (startPosition))
  645. continue;
  646. loop = false;
  647. break;
  648. }
  649. if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
  650. // Note that if _nav contains only 1 node, it won't be Same.
  651. finished = true;
  652. return false;
  653. } else {
  654. _pos ++;
  655. // This cannot be omitted
  656. _current = _nav.Clone ();
  657. return true;
  658. }
  659. }
  660. public override bool ReverseAxis {
  661. get { return true; }
  662. }
  663. public override bool RequireSorting { get { return true; } }
  664. }
  665. internal class NamespaceIterator : SimpleIterator
  666. {
  667. public NamespaceIterator (BaseIterator iter) : base (iter) {}
  668. protected NamespaceIterator (NamespaceIterator other) : base (other) {}
  669. public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
  670. public override bool MoveNext ()
  671. {
  672. if (_pos == 0)
  673. {
  674. if (_nav.MoveToFirstNamespace ())
  675. {
  676. _pos ++;
  677. // This clone cannot be omitted
  678. _current = _nav.Clone ();
  679. return true;
  680. }
  681. }
  682. else if (_nav.MoveToNextNamespace ())
  683. {
  684. _pos ++;
  685. // This clone cannot be omitted
  686. _current = _nav.Clone ();
  687. return true;
  688. }
  689. return false;
  690. }
  691. public override bool ReverseAxis { get { return true; } }
  692. public override bool RequireSorting { get { return false; } }
  693. }
  694. internal class AttributeIterator : SimpleIterator
  695. {
  696. public AttributeIterator (BaseIterator iter) : base (iter) {}
  697. protected AttributeIterator (AttributeIterator other) : base (other) {}
  698. public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
  699. public override bool MoveNext ()
  700. {
  701. if (_pos == 0)
  702. {
  703. if (_nav.MoveToFirstAttribute ())
  704. {
  705. _pos += 1;
  706. // This clone cannot be omitted
  707. _current = _nav.Clone ();
  708. return true;
  709. }
  710. }
  711. else if (_nav.MoveToNextAttribute ())
  712. {
  713. _pos ++;
  714. // This clone cannot be omitted
  715. _current = _nav.Clone ();
  716. return true;
  717. }
  718. return false;
  719. }
  720. public override bool RequireSorting { get { return false; } }
  721. }
  722. internal class AxisIterator : BaseIterator
  723. {
  724. protected SimpleIterator _iter;
  725. protected NodeTest _test;
  726. protected int _pos;
  727. string name, ns;
  728. XPathNodeType matchType;
  729. public AxisIterator (SimpleIterator iter, NodeTest test) : base (iter)
  730. {
  731. _iter = iter;
  732. _test = test;
  733. test.GetInfo (out name, out ns, out matchType, NamespaceManager);
  734. // if (name != null)
  735. // name = Current.NameTable.Add (name);
  736. // if (ns != null)
  737. // ns = Current.NameTable.Add (ns);
  738. }
  739. protected AxisIterator (AxisIterator other) : base (other)
  740. {
  741. _iter = (SimpleIterator) other._iter.Clone ();
  742. _test = other._test;
  743. _pos = other._pos;
  744. name = other.name;
  745. ns = other.ns;
  746. matchType = other.matchType;
  747. }
  748. public override XPathNodeIterator Clone () { return new AxisIterator (this); }
  749. public override bool MoveNext ()
  750. {
  751. while (_iter.MoveNext ())
  752. {
  753. if (_test.Match (NamespaceManager, Current))
  754. {
  755. _pos ++;
  756. return true;
  757. }
  758. }
  759. return false;
  760. }
  761. public override XPathNavigator Current { get { return _iter.Current; }}
  762. public override int CurrentPosition { get { return _pos; }}
  763. bool Match ()
  764. {
  765. if (Current.NodeType != matchType && matchType != XPathNodeType.All)
  766. return false;
  767. if (ns == null)
  768. return name == null || (object)name == (object)Current.LocalName;
  769. else
  770. return (object)ns == (object)Current.NamespaceURI &&
  771. (name == null || (object)name == (object)Current.LocalName);
  772. }
  773. public override bool ReverseAxis {
  774. get { return _iter.ReverseAxis; }
  775. }
  776. public override bool RequireSorting { get { return _iter.RequireSorting; } }
  777. }
  778. internal class SlashIterator : BaseIterator
  779. {
  780. protected BaseIterator _iterLeft;
  781. protected BaseIterator _iterRight;
  782. protected NodeSet _expr;
  783. protected int _pos;
  784. ArrayList _navStore;
  785. SortedList _iterList;
  786. bool _finished;
  787. BaseIterator _nextIterRight;
  788. public SlashIterator (BaseIterator iter, NodeSet expr) : base (iter)
  789. {
  790. _iterLeft = iter;
  791. _expr = expr;
  792. }
  793. protected SlashIterator (SlashIterator other) : base (other)
  794. {
  795. _iterLeft = (BaseIterator) other._iterLeft.Clone ();
  796. if (other._iterRight != null)
  797. _iterRight = (BaseIterator) other._iterRight.Clone ();
  798. _expr = other._expr;
  799. _pos = other._pos;
  800. if (other._iterList != null)
  801. _iterList = (SortedList) other._iterList.Clone ();
  802. if (other._navStore != null)
  803. _navStore = (ArrayList) other._navStore.Clone ();
  804. _finished = other._finished;
  805. if (other._nextIterRight != null)
  806. _nextIterRight = (BaseIterator) other._nextIterRight.Clone ();
  807. }
  808. public override XPathNodeIterator Clone () { return new SlashIterator (this); }
  809. public override bool MoveNext ()
  810. {
  811. if (_finished)
  812. return false;
  813. if (RequireSorting) {
  814. if (_navStore == null) {
  815. CollectResults ();
  816. if (_navStore.Count == 0) {
  817. _finished = true;
  818. return false;
  819. }
  820. }
  821. _pos++;
  822. if (_navStore.Count < _pos) {
  823. _finished = true;
  824. _pos--;
  825. return false;
  826. }
  827. while (_navStore.Count > _pos) {
  828. if (((XPathNavigator) _navStore [_pos]).ComparePosition (
  829. (XPathNavigator) _navStore [_pos - 1]) == XmlNodeOrder.Same)
  830. _navStore.RemoveAt (_pos);
  831. else
  832. break;
  833. }
  834. return true;
  835. } else {
  836. if (_iterRight == null) { // First time
  837. if (!_iterLeft.MoveNext ())
  838. return false;
  839. _iterRight = _expr.EvaluateNodeSet (_iterLeft);
  840. _iterList = new SortedList (XPathIteratorComparer.Instance);
  841. }
  842. while (true) {
  843. while (!_iterRight.MoveNext ()) {
  844. if (_iterList.Count > 0) {
  845. int last = _iterList.Count - 1;
  846. BaseIterator tmpIter = (BaseIterator) _iterList.GetByIndex (last);
  847. _iterList.RemoveAt (last);
  848. switch (tmpIter.Current.ComparePosition (_iterRight.Current)) {
  849. case XmlNodeOrder.Same:
  850. case XmlNodeOrder.Before:
  851. _iterRight = tmpIter;
  852. continue;
  853. default:
  854. _iterRight = tmpIter;
  855. break;
  856. }
  857. break;
  858. } else if (_nextIterRight != null) {
  859. _iterRight = _nextIterRight;
  860. _nextIterRight = null;
  861. break;
  862. } else if (!_iterLeft.MoveNext ()) {
  863. _finished = true;
  864. return false;
  865. }
  866. else
  867. _iterRight = _expr.EvaluateNodeSet (_iterLeft);
  868. }
  869. bool loop = true;
  870. while (loop) {
  871. loop = false;
  872. if (_nextIterRight == null) {
  873. bool noMoreNext = false;
  874. while (_nextIterRight == null || !_nextIterRight.MoveNext ()) {
  875. if(_iterLeft.MoveNext ())
  876. _nextIterRight = _expr.EvaluateNodeSet (_iterLeft);
  877. else {
  878. noMoreNext = true;
  879. break;
  880. }
  881. }
  882. if (noMoreNext)
  883. _nextIterRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
  884. }
  885. if (_nextIterRight != null) {
  886. switch (_iterRight.Current.ComparePosition (_nextIterRight.Current)) {
  887. case XmlNodeOrder.After:
  888. _iterList.Add (_iterList.Count, _iterRight);
  889. _iterRight = _nextIterRight;
  890. _nextIterRight = null;
  891. loop = true;
  892. break;
  893. case XmlNodeOrder.Same:
  894. if (!_nextIterRight.MoveNext ())
  895. _nextIterRight = null;
  896. else {
  897. int last = _iterList.Count;
  898. if (last > 0) {
  899. _iterList.Add (last, _nextIterRight);
  900. _nextIterRight = (BaseIterator) _iterList.GetByIndex (last);
  901. _iterList.RemoveAt (last);
  902. }
  903. }
  904. loop = true;
  905. break;
  906. }
  907. }
  908. }
  909. _pos ++;
  910. return true;
  911. }
  912. }
  913. }
  914. private void CollectResults ()
  915. {
  916. if (_navStore != null)
  917. return;
  918. _navStore = new ArrayList ();
  919. while (true) {
  920. while (_iterRight == null || !_iterRight.MoveNext ()) {
  921. if (!_iterLeft.MoveNext ()) {
  922. _navStore.Sort (XPathNavigatorComparer.Instance);
  923. return;
  924. }
  925. _iterRight = _expr.EvaluateNodeSet (_iterLeft);
  926. }
  927. XPathNavigator nav = _iterRight.Current;
  928. _navStore.Add (_needClone ? nav.Clone () : nav);
  929. }
  930. }
  931. public override XPathNavigator Current {
  932. get {
  933. if (_pos <= 0) return null;
  934. if (RequireSorting) {
  935. return (XPathNavigator) _navStore [_pos - 1];
  936. } else {
  937. return _iterRight.Current;
  938. }
  939. }
  940. }
  941. public override int CurrentPosition { get { return _pos; }}
  942. public override bool RequireSorting {
  943. get {
  944. return _iterLeft.RequireSorting || _expr.RequireSorting;
  945. }
  946. }
  947. public override int Count { get { return _navStore == null ? base.Count : _navStore.Count; } }
  948. }
  949. internal class PredicateIterator : BaseIterator
  950. {
  951. protected BaseIterator _iter;
  952. protected Expression _pred;
  953. protected int _pos;
  954. protected XPathResultType resType;
  955. public PredicateIterator (BaseIterator iter, Expression pred) : base (iter)
  956. {
  957. _iter = iter;
  958. _pred = pred;
  959. resType = pred.GetReturnType (iter);
  960. }
  961. protected PredicateIterator (PredicateIterator other) : base (other)
  962. {
  963. _iter = (BaseIterator) other._iter.Clone ();
  964. _pred = other._pred;
  965. _pos = other._pos;
  966. resType = other.resType;
  967. }
  968. public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
  969. public override bool MoveNext ()
  970. {
  971. while (_iter.MoveNext ())
  972. {
  973. switch (resType) {
  974. case XPathResultType.Number:
  975. if (_pred.EvaluateNumber (_iter) != _iter.ComparablePosition)
  976. continue;
  977. break;
  978. case XPathResultType.Any: {
  979. object result = _pred.Evaluate (_iter);
  980. if (result is double)
  981. {
  982. if ((double) result != _iter.ComparablePosition)
  983. continue;
  984. }
  985. else if (!XPathFunctions.ToBoolean (result))
  986. continue;
  987. }
  988. break;
  989. default:
  990. if (!_pred.EvaluateBoolean (_iter))
  991. continue;
  992. break;
  993. }
  994. _pos ++;
  995. return true;
  996. }
  997. return false;
  998. }
  999. public override XPathNavigator Current { get { return _iter.Current; }}
  1000. public override int CurrentPosition { get { return _pos; }}
  1001. public override bool ReverseAxis {
  1002. get { return _iter.ReverseAxis; }
  1003. }
  1004. public override bool RequireSorting { get { return true; } }
  1005. }
  1006. internal class ListIterator : BaseIterator
  1007. {
  1008. protected IList _list;
  1009. protected int _pos;
  1010. bool _requireSorting;
  1011. public ListIterator (BaseIterator iter, IList list, bool requireSorting) : base (iter)
  1012. {
  1013. if (!(list is ICloneable))
  1014. throw new ArgumentException ("Target enumerator must be cloneable.");
  1015. _list = list;
  1016. _requireSorting = requireSorting;
  1017. }
  1018. public ListIterator (IList list, NSResolver nsm, bool requireSorting) : base (nsm)
  1019. {
  1020. if (!(list is ICloneable))
  1021. throw new ArgumentException ("Target enumerator must be cloneable.");
  1022. _list = list;
  1023. _requireSorting = requireSorting;
  1024. }
  1025. protected ListIterator (ListIterator other) : base (other)
  1026. {
  1027. ICloneable listClone = other._list as ICloneable;
  1028. _list = (IList) listClone.Clone ();
  1029. _pos = other._pos;
  1030. _requireSorting = other._requireSorting;
  1031. }
  1032. public override XPathNodeIterator Clone () { return new ListIterator (this); }
  1033. public override bool MoveNext ()
  1034. {
  1035. if (_pos >= _list.Count)
  1036. return false;
  1037. _pos++;
  1038. return true;
  1039. }
  1040. public override XPathNavigator Current {
  1041. get {
  1042. if (_list.Count == 0)
  1043. return null;
  1044. return (XPathNavigator) _list [_pos - 1];
  1045. }
  1046. }
  1047. public override int CurrentPosition { get { return _pos; }}
  1048. public override bool RequireSorting { get { return _requireSorting; } }
  1049. public override int Count { get { return _list.Count; } }
  1050. }
  1051. internal class UnionIterator : BaseIterator
  1052. {
  1053. protected BaseIterator _left, _right;
  1054. private int _pos;
  1055. private bool keepLeft;
  1056. private bool keepRight;
  1057. private bool useRight;
  1058. public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter)
  1059. {
  1060. _left = left;
  1061. _right = right;
  1062. }
  1063. protected UnionIterator (UnionIterator other) : base (other)
  1064. {
  1065. _left = (BaseIterator) other._left.Clone ();
  1066. _right = (BaseIterator) other._right.Clone ();
  1067. _pos = other._pos;
  1068. keepLeft = other.keepLeft;
  1069. keepRight = other.keepRight;
  1070. useRight = other.useRight;
  1071. }
  1072. public override XPathNodeIterator Clone () { return new UnionIterator (this); }
  1073. public override bool MoveNext ()
  1074. {
  1075. if (!keepLeft)
  1076. keepLeft = _left.MoveNext ();
  1077. if (!keepRight)
  1078. keepRight = _right.MoveNext ();
  1079. if (!keepLeft && !keepRight)
  1080. return false;
  1081. _pos ++;
  1082. if (!keepRight) {
  1083. keepLeft = useRight = false;
  1084. return true;
  1085. } else if (!keepLeft) {
  1086. keepRight = false;
  1087. useRight = true;
  1088. return true;
  1089. }
  1090. switch (_left.Current.ComparePosition (_right.Current)) {
  1091. case XmlNodeOrder.Same:
  1092. // consume both. i.e. don't output duplicate result.
  1093. keepLeft = keepRight = false;
  1094. useRight = true;
  1095. return true;
  1096. case XmlNodeOrder.Before:
  1097. case XmlNodeOrder.Unknown: // Maybe happen because of "document(a) | document(b)"
  1098. keepLeft = useRight = false;
  1099. return true;
  1100. case XmlNodeOrder.After:
  1101. keepRight = false;
  1102. useRight = true;
  1103. return true;
  1104. default:
  1105. throw new InvalidOperationException ("Should not happen.");
  1106. }
  1107. }
  1108. public override XPathNavigator Current
  1109. {
  1110. get
  1111. {
  1112. if (_pos == 0)
  1113. return null;
  1114. if (useRight)
  1115. return _right.Current;
  1116. else
  1117. return _left.Current;
  1118. }
  1119. }
  1120. public override int CurrentPosition { get { return _pos; }}
  1121. public override bool RequireSorting { get { return _left.RequireSorting || _right.RequireSorting; } }
  1122. }
  1123. }