Iterator.cs 31 KB

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