Iterator.cs 30 KB

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