Iterator.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  1. //
  2. // System.Xml.XPath.BaseIterator
  3. //
  4. // Author:
  5. // Piers Haken ([email protected])
  6. //
  7. // (C) 2002 Piers Haken
  8. //
  9. using System;
  10. using System.Collections;
  11. using System.Xml;
  12. using System.Xml.XPath;
  13. using System.Xml.Xsl;
  14. namespace System.Xml.XPath
  15. {
  16. internal abstract class BaseIterator : XPathNodeIterator
  17. {
  18. private XmlNamespaceManager _nsm;
  19. internal BaseIterator (BaseIterator other)
  20. {
  21. _nsm = other._nsm;
  22. }
  23. internal BaseIterator (XmlNamespaceManager nsm)
  24. {
  25. _nsm = nsm;
  26. }
  27. public XmlNamespaceManager NamespaceManager
  28. {
  29. get { return _nsm; }
  30. set { _nsm = value; }
  31. }
  32. public virtual bool ReverseAxis {
  33. get { return false; }
  34. }
  35. public virtual int ComparablePosition {
  36. get {
  37. if (ReverseAxis) {
  38. int diff = Count - CurrentPosition + 1;
  39. return diff < 1 ? 1 : diff;
  40. }
  41. else
  42. return CurrentPosition;
  43. }
  44. }
  45. public override string ToString ()
  46. {
  47. if (Current != null)
  48. return Current.NodeType.ToString () + "[" + CurrentPosition + "] : " + Current.Name + " = " + Current.Value;
  49. else
  50. return this.GetType().ToString () + "[" + CurrentPosition + "]";
  51. }
  52. }
  53. internal class MergedIterator : BaseIterator
  54. {
  55. protected ArrayList _iters = new ArrayList ();
  56. protected int _pos;
  57. protected int _index;
  58. public MergedIterator (BaseIterator iter ) : base (iter) {}
  59. protected MergedIterator (MergedIterator other) : base (other)
  60. {
  61. foreach (XPathNodeIterator iter in other._iters)
  62. _iters.Add (iter.Clone ());
  63. _pos = other._pos;
  64. _index = other._index;
  65. }
  66. public override XPathNodeIterator Clone () { return new MergedIterator (this); }
  67. public void Add (BaseIterator iter)
  68. {
  69. _iters.Add (iter);
  70. }
  71. public override bool MoveNext ()
  72. {
  73. while (_index < _iters.Count)
  74. {
  75. BaseIterator iter = (BaseIterator) _iters [_index];
  76. if (iter.MoveNext ())
  77. {
  78. _pos ++;
  79. return true;
  80. }
  81. _index ++;
  82. }
  83. return false;
  84. }
  85. public override XPathNavigator Current
  86. {
  87. get
  88. {
  89. if (_index >= _iters.Count)
  90. return null;
  91. BaseIterator iter = (BaseIterator) _iters [_index];
  92. return iter.Current;
  93. }
  94. }
  95. public override int CurrentPosition { get { return _pos; }}
  96. }
  97. internal abstract class SimpleIterator : BaseIterator
  98. {
  99. protected readonly XPathNavigator _nav;
  100. protected int _pos;
  101. public SimpleIterator (BaseIterator iter) : base (iter)
  102. {
  103. _nav = iter.Current.Clone ();
  104. }
  105. protected SimpleIterator (SimpleIterator other) : base (other)
  106. {
  107. _nav = other._nav.Clone ();
  108. _pos = other._pos;
  109. }
  110. public SimpleIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nsm)
  111. {
  112. _nav = nav.Clone ();
  113. }
  114. public override XPathNavigator Current { get { return _nav; }}
  115. public override int CurrentPosition { get { return _pos; }}
  116. }
  117. internal class SelfIterator : SimpleIterator
  118. {
  119. public SelfIterator (BaseIterator iter) : base (iter) {}
  120. public SelfIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
  121. protected SelfIterator (SelfIterator other) : base (other) {}
  122. public override XPathNodeIterator Clone () { return new SelfIterator (this); }
  123. public override bool MoveNext ()
  124. {
  125. if (_pos == 0)
  126. {
  127. _pos = 1;
  128. return true;
  129. }
  130. return false;
  131. }
  132. }
  133. internal class NullIterator : SelfIterator
  134. {
  135. public NullIterator (BaseIterator iter) : base (iter) {}
  136. public NullIterator (XPathNavigator nav) : this (nav, null) {}
  137. public NullIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
  138. protected NullIterator (NullIterator other) : base (other) {}
  139. public override XPathNodeIterator Clone () { return new NullIterator (this); }
  140. public override bool MoveNext ()
  141. {
  142. return false;
  143. }
  144. }
  145. internal class ParentIterator : SimpleIterator
  146. {
  147. public ParentIterator (BaseIterator iter) : base (iter) {}
  148. protected ParentIterator (ParentIterator other) : base (other) {}
  149. public ParentIterator (XPathNavigator nav, XmlNamespaceManager nsm) : base (nav, nsm) {}
  150. public override XPathNodeIterator Clone () { return new ParentIterator (this); }
  151. public override bool MoveNext ()
  152. {
  153. if (_pos == 0 && _nav.MoveToParent ())
  154. {
  155. _pos = 1;
  156. return true;
  157. }
  158. return false;
  159. }
  160. }
  161. internal class ChildIterator : SimpleIterator
  162. {
  163. public ChildIterator (BaseIterator iter) : base (iter) {}
  164. protected ChildIterator (ChildIterator other) : base (other) {}
  165. public override XPathNodeIterator Clone () { return new ChildIterator (this); }
  166. public override bool MoveNext ()
  167. {
  168. bool fSuccess = (_pos == 0) ? _nav.MoveToFirstChild () : _nav.MoveToNext ();
  169. if (fSuccess)
  170. _pos ++;
  171. return fSuccess;
  172. }
  173. }
  174. internal class FollowingSiblingIterator : SimpleIterator
  175. {
  176. public FollowingSiblingIterator (BaseIterator iter) : base (iter) {}
  177. protected FollowingSiblingIterator (FollowingSiblingIterator other) : base (other) {}
  178. public override XPathNodeIterator Clone () { return new FollowingSiblingIterator (this); }
  179. public override bool MoveNext ()
  180. {
  181. if (_nav.MoveToNext ())
  182. {
  183. _pos ++;
  184. return true;
  185. }
  186. return false;
  187. }
  188. }
  189. internal class PrecedingSiblingIterator : SimpleIterator
  190. {
  191. bool finished;
  192. bool started;
  193. XPathNavigator startPosition;
  194. public PrecedingSiblingIterator (BaseIterator iter) : base (iter)
  195. {
  196. startPosition = iter.Current.Clone ();
  197. }
  198. protected PrecedingSiblingIterator (PrecedingSiblingIterator other) : base (other)
  199. {
  200. startPosition = other.startPosition;
  201. started = other.started;
  202. finished = other.finished;
  203. }
  204. public override XPathNodeIterator Clone () { return new PrecedingSiblingIterator (this); }
  205. public override bool MoveNext ()
  206. {
  207. if (finished)
  208. return false;
  209. if (!started) {
  210. started = true;
  211. _nav.MoveToFirst ();
  212. if (_nav.ComparePosition (startPosition) == XmlNodeOrder.Same) {
  213. _pos++;
  214. return true;
  215. }
  216. } else {
  217. if (!_nav.MoveToNext ()) {
  218. finished = true;
  219. return false;
  220. }
  221. }
  222. if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
  223. // Note that if _nav contains only 1 node, it won't be Same.
  224. finished = true;
  225. return false;
  226. } else {
  227. _pos ++;
  228. return true;
  229. }
  230. }
  231. public override bool ReverseAxis {
  232. get { return true; }
  233. }
  234. }
  235. internal class AncestorIterator : SimpleIterator
  236. {
  237. bool finished;
  238. bool started;
  239. ArrayList positions = new ArrayList ();
  240. XPathNavigator startPosition;
  241. int nextDepth;
  242. public AncestorIterator (BaseIterator iter) : base (iter)
  243. {
  244. startPosition = iter.Current.Clone ();
  245. }
  246. protected AncestorIterator (AncestorIterator other) : base (other)
  247. {
  248. startPosition = other.startPosition;
  249. started = other.started;
  250. finished = other.finished;
  251. positions = other.positions;
  252. nextDepth = other.nextDepth;
  253. }
  254. public override XPathNodeIterator Clone () { return new AncestorIterator (this); }
  255. public override bool MoveNext ()
  256. {
  257. if (finished)
  258. return false;
  259. if (!started) {
  260. started = true;
  261. XPathNavigator ancestors = startPosition.Clone ();
  262. ancestors.MoveToParent ();
  263. _nav.MoveToParent ();
  264. do {
  265. int i = 0;
  266. _nav.MoveToFirst ();
  267. while (_nav.ComparePosition (ancestors) == XmlNodeOrder.Before) {
  268. _nav.MoveToNext ();
  269. i++;
  270. }
  271. positions.Add (i);
  272. ancestors.MoveToParent ();
  273. _nav.MoveToParent ();
  274. } while (ancestors.NodeType != XPathNodeType.Root);
  275. positions.Reverse ();
  276. }
  277. if (nextDepth < positions.Count) {
  278. int thisTimePos = (int) positions [nextDepth];
  279. _nav.MoveToFirstChild ();
  280. for (int i = 0; i < thisTimePos; i++)
  281. _nav.MoveToNext ();
  282. nextDepth++;
  283. _pos++;
  284. return true;
  285. }
  286. finished = true;
  287. return false;
  288. }
  289. public override bool ReverseAxis {
  290. get { return true; }
  291. }
  292. }
  293. internal class AncestorOrSelfIterator : SimpleIterator
  294. {
  295. bool finished;
  296. bool started;
  297. ArrayList positions = new ArrayList ();
  298. XPathNavigator startPosition;
  299. int nextDepth;
  300. public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
  301. {
  302. startPosition = iter.Current.Clone ();
  303. }
  304. protected AncestorOrSelfIterator (AncestorOrSelfIterator other) : base (other)
  305. {
  306. startPosition = other.startPosition;
  307. started = other.started;
  308. finished = other.finished;
  309. positions = other.positions;
  310. nextDepth = other.nextDepth;
  311. }
  312. public override XPathNodeIterator Clone () { return new AncestorOrSelfIterator (this); }
  313. public override bool MoveNext ()
  314. {
  315. if (finished)
  316. return false;
  317. if (!started) {
  318. started = true;
  319. XPathNavigator ancestors = startPosition.Clone ();
  320. do {
  321. int i = 0;
  322. _nav.MoveToFirst ();
  323. while (_nav.ComparePosition (ancestors) == XmlNodeOrder.Before) {
  324. _nav.MoveToNext ();
  325. i++;
  326. }
  327. positions.Add (i);
  328. ancestors.MoveToParent ();
  329. _nav.MoveToParent ();
  330. } while (ancestors.NodeType != XPathNodeType.Root);
  331. positions.Reverse ();
  332. }
  333. if (nextDepth < positions.Count) {
  334. int thisTimePos = (int) positions [nextDepth];
  335. _nav.MoveToFirstChild ();
  336. for (int i = 0; i < thisTimePos; i++)
  337. _nav.MoveToNext ();
  338. nextDepth++;
  339. _pos++;
  340. return true;
  341. }
  342. finished = true;
  343. return false;
  344. }
  345. public override bool ReverseAxis {
  346. get { return true; }
  347. }
  348. }
  349. internal class DescendantIterator : SimpleIterator
  350. {
  351. protected int _depth;
  352. private bool _finished;
  353. public DescendantIterator (BaseIterator iter) : base (iter) {}
  354. protected DescendantIterator (DescendantIterator other) : base (other)
  355. {
  356. _depth = other._depth;
  357. }
  358. public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
  359. [MonoTODO]
  360. public override bool MoveNext ()
  361. {
  362. if (_finished)
  363. return false;
  364. if (_nav.MoveToFirstChild ())
  365. {
  366. _depth ++;
  367. _pos ++;
  368. return true;
  369. }
  370. while (_depth != 0)
  371. {
  372. if (_nav.MoveToNext ())
  373. {
  374. _pos ++;
  375. return true;
  376. }
  377. if (!_nav.MoveToParent ()) // should NEVER fail!
  378. throw new XPathException ("unexpected depth"); // TODO: better message
  379. _depth --;
  380. }
  381. _finished = true;
  382. return false;
  383. }
  384. }
  385. internal class DescendantOrSelfIterator : SimpleIterator
  386. {
  387. protected int _depth;
  388. private bool _finished;
  389. public DescendantOrSelfIterator (BaseIterator iter) : base (iter) {}
  390. protected DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other)
  391. {
  392. _depth = other._depth;
  393. }
  394. public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
  395. [MonoTODO]
  396. public override bool MoveNext ()
  397. {
  398. if (_finished)
  399. return false;
  400. if (_pos == 0)
  401. {
  402. // self
  403. _pos ++;
  404. return true;
  405. }
  406. if (_nav.MoveToFirstChild ())
  407. {
  408. _depth ++;
  409. _pos ++;
  410. return true;
  411. }
  412. while (_depth != 0)
  413. {
  414. if (_nav.MoveToNext ())
  415. {
  416. _pos ++;
  417. return true;
  418. }
  419. if (!_nav.MoveToParent ()) // should NEVER fail!
  420. throw new XPathException ("unexpected depth"); // TODO: better message
  421. _depth --;
  422. }
  423. _finished = true;
  424. return false;
  425. }
  426. }
  427. internal class FollowingIterator : SimpleIterator
  428. {
  429. private bool _finished = false;
  430. public FollowingIterator (BaseIterator iter) : base (iter) {}
  431. protected FollowingIterator (FollowingIterator other) : base (other) {}
  432. public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
  433. public override bool MoveNext ()
  434. {
  435. if (_finished)
  436. return false;
  437. if (_pos == 0)
  438. {
  439. if (_nav.MoveToNext ())
  440. {
  441. _pos ++;
  442. return true;
  443. }
  444. }
  445. else
  446. {
  447. if (_nav.MoveToFirstChild ())
  448. {
  449. _pos ++;
  450. return true;
  451. }
  452. do
  453. {
  454. if (_nav.MoveToNext ())
  455. {
  456. _pos ++;
  457. return true;
  458. }
  459. }
  460. while (_nav.MoveToParent ());
  461. }
  462. _finished = true;
  463. return false;
  464. }
  465. }
  466. internal class PrecedingIterator : SimpleIterator
  467. {
  468. bool finished;
  469. bool started;
  470. XPathNavigator startPosition;
  471. public PrecedingIterator (BaseIterator iter) : base (iter)
  472. {
  473. startPosition = iter.Current.Clone ();
  474. }
  475. protected PrecedingIterator (PrecedingIterator other) : base (other)
  476. {
  477. startPosition = other.startPosition;
  478. started = other.started;
  479. finished = other.finished;
  480. }
  481. public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
  482. public override bool MoveNext ()
  483. {
  484. if (finished)
  485. return false;
  486. if (!started) {
  487. started = true;
  488. _nav.MoveToRoot ();
  489. _nav.MoveToFirstChild ();
  490. if (_nav.ComparePosition (startPosition) == XmlNodeOrder.Same) {
  491. _pos++;
  492. return true;
  493. }
  494. } else {
  495. while (!_nav.MoveToFirstChild ()) {
  496. while (!_nav.MoveToNext ())
  497. _nav.MoveToParent (); // Should not finish, at least before startPosition.
  498. break;
  499. }
  500. }
  501. if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
  502. // Note that if _nav contains only 1 node, it won't be Same.
  503. finished = true;
  504. return false;
  505. } else {
  506. _pos ++;
  507. return true;
  508. }
  509. }
  510. public override bool ReverseAxis {
  511. get { return true; }
  512. }
  513. }
  514. internal class NamespaceIterator : SimpleIterator
  515. {
  516. public NamespaceIterator (BaseIterator iter) : base (iter) {}
  517. protected NamespaceIterator (NamespaceIterator other) : base (other) {}
  518. public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
  519. public override bool MoveNext ()
  520. {
  521. if (_pos == 0)
  522. {
  523. if (_nav.MoveToFirstNamespace ())
  524. {
  525. _pos ++;
  526. return true;
  527. }
  528. }
  529. else if (_nav.MoveToNextNamespace ())
  530. {
  531. _pos ++;
  532. return true;
  533. }
  534. return false;
  535. }
  536. }
  537. internal class AttributeIterator : SimpleIterator
  538. {
  539. public AttributeIterator (BaseIterator iter) : base (iter) {}
  540. protected AttributeIterator (AttributeIterator other) : base (other) {}
  541. public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
  542. public override bool MoveNext ()
  543. {
  544. if (_pos == 0)
  545. {
  546. if (_nav.MoveToFirstAttribute ())
  547. {
  548. _pos += 1;
  549. return true;
  550. }
  551. }
  552. else if (_nav.MoveToNextAttribute ())
  553. {
  554. _pos ++;
  555. return true;
  556. }
  557. return false;
  558. }
  559. }
  560. internal class AxisIterator : BaseIterator
  561. {
  562. protected SimpleIterator _iter;
  563. protected NodeTest _test;
  564. protected int _pos;
  565. string name, ns;
  566. XPathNodeType matchType;
  567. public AxisIterator (SimpleIterator iter, NodeTest test) : base (iter)
  568. {
  569. _iter = iter;
  570. _test = test;
  571. test.GetInfo (out name, out ns, out matchType, NamespaceManager);
  572. if (name != null)
  573. name = Current.NameTable.Add (name);
  574. if (ns != null)
  575. ns = Current.NameTable.Add (ns);
  576. }
  577. protected AxisIterator (AxisIterator other) : base (other)
  578. {
  579. _iter = (SimpleIterator) other._iter.Clone ();
  580. _test = other._test;
  581. _pos = other._pos;
  582. name = other.name;
  583. ns = other.ns;
  584. matchType = other.matchType;
  585. }
  586. public override XPathNodeIterator Clone () { return new AxisIterator (this); }
  587. public override bool MoveNext ()
  588. {
  589. while (_iter.MoveNext ())
  590. {
  591. if (_test.Match (NamespaceManager, Current))
  592. {
  593. _pos ++;
  594. return true;
  595. }
  596. }
  597. return false;
  598. }
  599. public override XPathNavigator Current { get { return _iter.Current; }}
  600. public override int CurrentPosition { get { return _pos; }}
  601. //public override int ComparablePosition { get { return _iter.ComparablePosition; } }
  602. bool Match ()
  603. {
  604. if (Current.NodeType != matchType && matchType != XPathNodeType.All)
  605. return false;
  606. if (ns == null)
  607. return name == null || (object)name == (object)Current.LocalName;
  608. else
  609. return (object)ns == (object)Current.NamespaceURI &&
  610. (name == null || (object)name == (object)Current.LocalName);
  611. }
  612. }
  613. #if false
  614. internal class SlashIterator : BaseIterator
  615. {
  616. protected BaseIterator _iterLeft;
  617. protected BaseIterator _iterRight;
  618. protected NodeSet _expr;
  619. protected int _pos;
  620. public SlashIterator (BaseIterator iter, NodeSet expr) : base (iter)
  621. {
  622. _iterLeft = iter;
  623. _expr = expr;
  624. }
  625. protected SlashIterator (SlashIterator other) : base (other)
  626. {
  627. _iterLeft = (BaseIterator) other._iterLeft.Clone ();
  628. if (other._iterRight != null)
  629. _iterRight = (BaseIterator) other._iterRight.Clone ();
  630. _expr = other._expr;
  631. _pos = other._pos;
  632. }
  633. public override XPathNodeIterator Clone () { return new SlashIterator (this); }
  634. public override bool MoveNext ()
  635. {
  636. while (_iterRight == null || !_iterRight.MoveNext ())
  637. {
  638. if (!_iterLeft.MoveNext ())
  639. return false;
  640. _iterRight = _expr.EvaluateNodeSet (_iterLeft);
  641. }
  642. _pos ++;
  643. return true;
  644. }
  645. public override XPathNavigator Current {
  646. get {
  647. if (_iterRight == null) return null;
  648. return _iterRight.Current;
  649. }
  650. }
  651. public override int CurrentPosition { get { return _pos; }}
  652. }
  653. #else
  654. internal class SlashIterator : BaseIterator
  655. {
  656. protected BaseIterator _iterLeft;
  657. protected BaseIterator _iterRight;
  658. protected NodeSet _expr;
  659. protected int _pos;
  660. Stack _iterStack;
  661. bool _finished;
  662. BaseIterator _nextIterRight;
  663. public SlashIterator (BaseIterator iter, NodeSet expr) : base (iter)
  664. {
  665. _iterLeft = iter;
  666. _expr = expr;
  667. }
  668. protected SlashIterator (SlashIterator other) : base (other)
  669. {
  670. _iterLeft = (BaseIterator) other._iterLeft.Clone ();
  671. if (other._iterRight != null)
  672. _iterRight = (BaseIterator) other._iterRight.Clone ();
  673. _expr = other._expr;
  674. _pos = other._pos;
  675. if (other._iterStack != null)
  676. _iterStack = other._iterStack.Clone () as Stack;
  677. _finished = other._finished;
  678. _nextIterRight = other._nextIterRight;
  679. }
  680. public override XPathNodeIterator Clone () { return new SlashIterator (this); }
  681. public override bool MoveNext ()
  682. {
  683. if (_finished)
  684. return false;
  685. if (_iterRight == null) {
  686. if (!_iterLeft.MoveNext ())
  687. return false;
  688. _iterRight = _expr.EvaluateNodeSet (_iterLeft);
  689. _iterStack = new Stack ();
  690. }
  691. while (true) {
  692. while (!_iterRight.MoveNext ()) {
  693. if (_iterStack.Count > 0) {
  694. _iterRight = _iterStack.Pop () as BaseIterator;
  695. break;
  696. } else if (_nextIterRight != null) {
  697. _iterRight = _nextIterRight;
  698. _nextIterRight = null;
  699. break;
  700. } else if (!_iterLeft.MoveNext ()) {
  701. _finished = true;
  702. return false;
  703. }
  704. else
  705. _iterRight = _expr.EvaluateNodeSet (_iterLeft);
  706. }
  707. bool loop = true;
  708. while (loop) {
  709. loop = false;
  710. if (_nextIterRight == null) {
  711. bool noMoreNext = false;
  712. while (_nextIterRight == null || !_nextIterRight.MoveNext ()) {
  713. if(_iterLeft.MoveNext ())
  714. _nextIterRight = _expr.EvaluateNodeSet (_iterLeft);
  715. else {
  716. noMoreNext = true;
  717. break;
  718. }
  719. }
  720. if (noMoreNext)
  721. _nextIterRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
  722. }
  723. if (_nextIterRight != null) {
  724. switch (_iterRight.Current.ComparePosition (_nextIterRight.Current)) {
  725. case XmlNodeOrder.After:
  726. _iterStack.Push (_iterRight);
  727. _iterRight = _nextIterRight;
  728. _nextIterRight = null;
  729. break;
  730. case XmlNodeOrder.Same:
  731. if (!_nextIterRight.MoveNext ())
  732. _nextIterRight = null;
  733. loop = true;
  734. break;
  735. }
  736. }
  737. }
  738. _pos ++;
  739. return true;
  740. }
  741. }
  742. public override XPathNavigator Current {
  743. get {
  744. if (_iterRight == null) return null;
  745. return _iterRight.Current;
  746. }
  747. }
  748. public override int CurrentPosition { get { return _pos; }}
  749. }
  750. #endif
  751. internal class PredicateIterator : BaseIterator
  752. {
  753. protected BaseIterator _iter;
  754. protected Expression _pred;
  755. protected int _pos;
  756. protected XPathResultType resType;
  757. public PredicateIterator (BaseIterator iter, Expression pred) : base (iter)
  758. {
  759. _iter = iter;
  760. _pred = pred;
  761. resType = pred.GetReturnType (iter);
  762. }
  763. protected PredicateIterator (PredicateIterator other) : base (other)
  764. {
  765. _iter = (BaseIterator) other._iter.Clone ();
  766. _pred = other._pred;
  767. _pos = other._pos;
  768. resType = other.resType;
  769. }
  770. public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
  771. public override bool MoveNext ()
  772. {
  773. while (_iter.MoveNext ())
  774. {
  775. bool fTrue = true;
  776. switch (resType) {
  777. case XPathResultType.Number:
  778. if (_pred.EvaluateNumber (_iter) != _iter.ComparablePosition)
  779. continue;
  780. break;
  781. case XPathResultType.Any: {
  782. object result = _pred.Evaluate (_iter);
  783. if (result is double)
  784. {
  785. if ((double) result != _iter.ComparablePosition)
  786. continue;
  787. }
  788. else if (!XPathFunctions.ToBoolean (result))
  789. continue;
  790. }
  791. break;
  792. default:
  793. if (!_pred.EvaluateBoolean (_iter))
  794. continue;
  795. break;
  796. }
  797. _pos ++;
  798. return true;
  799. }
  800. return false;
  801. }
  802. public override XPathNavigator Current { get { return _iter.Current; }}
  803. public override int CurrentPosition { get { return _pos; }}
  804. }
  805. internal class EnumeratorIterator : BaseIterator
  806. {
  807. protected IEnumerator _enum;
  808. protected int _pos;
  809. public EnumeratorIterator (BaseIterator iter, IEnumerator enumerator) : base (iter)
  810. {
  811. _enum = enumerator;
  812. }
  813. public EnumeratorIterator (IEnumerator enumerator, XmlNamespaceManager nsm) : base (nsm)
  814. {
  815. _enum = enumerator;
  816. }
  817. protected EnumeratorIterator (EnumeratorIterator other) : base (other)
  818. {
  819. _enum = other._enum;
  820. _pos = other._pos;
  821. }
  822. public override XPathNodeIterator Clone () { return new EnumeratorIterator (this); }
  823. public override bool MoveNext ()
  824. {
  825. if (!_enum.MoveNext ())
  826. return false;
  827. _pos++;
  828. return true;
  829. }
  830. public override XPathNavigator Current { get { return (XPathNavigator) _enum.Current; }}
  831. public override int CurrentPosition { get { return _pos; }}
  832. }
  833. internal class UnionIterator : BaseIterator
  834. {
  835. protected BaseIterator _left, _right;
  836. private int _pos;
  837. private bool keepLeft;
  838. private bool keepRight;
  839. private bool useRight;
  840. public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter)
  841. {
  842. _left = left;
  843. _right = right;
  844. }
  845. protected UnionIterator (UnionIterator other) : base (other)
  846. {
  847. _left = other._left;
  848. _right = other._right;
  849. _pos = other._pos;
  850. }
  851. public override XPathNodeIterator Clone () { return new UnionIterator (this); }
  852. public override bool MoveNext ()
  853. {
  854. if (!keepLeft)
  855. keepLeft = _left.MoveNext ();
  856. if (!keepRight)
  857. keepRight = _right.MoveNext ();
  858. if (!keepLeft && !keepRight)
  859. return false;
  860. _pos ++;
  861. if (!keepRight) {
  862. keepLeft = useRight = false;
  863. return true;
  864. } else if (!keepLeft) {
  865. keepRight = false;
  866. useRight = true;
  867. return true;
  868. }
  869. switch (_left.Current.ComparePosition (_right.Current)) {
  870. case XmlNodeOrder.Same:
  871. // consume both. i.e. don't output duplicate result.
  872. keepLeft = keepRight = false;
  873. useRight = true;
  874. return true;
  875. case XmlNodeOrder.Before:
  876. keepLeft = useRight = false;
  877. return true;
  878. case XmlNodeOrder.After:
  879. keepRight = false;
  880. useRight = true;
  881. return true;
  882. default:
  883. throw new InvalidOperationException ("Should not happen.");
  884. }
  885. }
  886. public override XPathNavigator Current
  887. {
  888. get
  889. {
  890. if (_pos == 0)
  891. return null;
  892. if (useRight)
  893. return _right.Current;
  894. else
  895. return _left.Current;
  896. }
  897. }
  898. public override int CurrentPosition { get { return _pos; }}
  899. }
  900. }