Iterator.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221
  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. if (!ancestors.MoveToParent ())
  297. break; // It is for detached nodes under XmlDocumentNavigator
  298. _nav.MoveToParent ();
  299. }
  300. positions.Reverse ();
  301. if (startPosition.NodeType != XPathNodeType.Root) {
  302. // First time it returns Root
  303. _pos++;
  304. // This clone cannot be omitted
  305. _current = _nav.Clone ();
  306. return true;
  307. }
  308. }
  309. // Don't worry about node type of start position, like AncestorOrSelf.
  310. // It should be Element or Root.
  311. if (nextDepth < positions.Count) {
  312. int thisTimePos = (int) positions [nextDepth];
  313. _nav.MoveToFirstChild ();
  314. for (int i = 0; i < thisTimePos; i++)
  315. _nav.MoveToNext ();
  316. nextDepth++;
  317. _pos++;
  318. // This clone cannot be omitted
  319. _current = _nav.Clone ();
  320. return true;
  321. }
  322. finished = true;
  323. return false;
  324. }
  325. public override bool ReverseAxis {
  326. get { return true; }
  327. }
  328. public override bool RequireSorting { get { return true; } }
  329. public override int Count { get { return positions.Count; } }
  330. }
  331. internal class AncestorOrSelfIterator : SimpleIterator
  332. {
  333. bool finished;
  334. bool started;
  335. ArrayList positions = new ArrayList ();
  336. XPathNavigator startPosition;
  337. int nextDepth;
  338. public AncestorOrSelfIterator (BaseIterator iter) : base (iter)
  339. {
  340. startPosition = iter.Current.Clone ();
  341. _current = startPosition.Clone ();
  342. }
  343. protected AncestorOrSelfIterator (AncestorOrSelfIterator other) : base (other)
  344. {
  345. startPosition = other.startPosition;
  346. started = other.started;
  347. finished = other.finished;
  348. positions = (ArrayList) other.positions.Clone ();
  349. nextDepth = other.nextDepth;
  350. _current = other._current.Clone ();
  351. }
  352. public override XPathNodeIterator Clone () { return new AncestorOrSelfIterator (this); }
  353. public override bool MoveNext ()
  354. {
  355. bool initialIteration = false;
  356. if (finished)
  357. return false;
  358. if (!started) {
  359. initialIteration = true;
  360. started = true;
  361. // This clone cannot be omitted
  362. XPathNavigator ancestors = startPosition.Clone ();
  363. do {
  364. int i = 0;
  365. _nav.MoveToFirst ();
  366. while (_nav.ComparePosition (ancestors) == XmlNodeOrder.Before) {
  367. _nav.MoveToNext ();
  368. i++;
  369. }
  370. positions.Add (i);
  371. if (!ancestors.MoveToParent ())
  372. break; // for detached nodes under XmlDocumentNavigator.
  373. _nav.MoveToParent ();
  374. } while (ancestors.NodeType != XPathNodeType.Root);
  375. positions.Reverse ();
  376. }
  377. if (initialIteration && startPosition.NodeType != XPathNodeType.Root) {
  378. // This clone cannot be omitted
  379. _current = _nav.Clone ();
  380. return true;
  381. } else if (nextDepth + 1 == positions.Count) {
  382. nextDepth++;
  383. _pos++;
  384. _nav.MoveTo (startPosition);
  385. // This clone cannot be omitted
  386. _current = _nav.Clone ();
  387. return true;
  388. }
  389. else if (nextDepth < positions.Count) {
  390. int thisTimePos = (int) positions [nextDepth];
  391. _nav.MoveToFirstChild ();
  392. for (int i = 0; i < thisTimePos; i++)
  393. _nav.MoveToNext ();
  394. nextDepth++;
  395. _pos++;
  396. // This clone cannot be omitted
  397. _current = _nav.Clone ();
  398. return true;
  399. }
  400. finished = true;
  401. return false;
  402. }
  403. public override bool ReverseAxis {
  404. get { return true; }
  405. }
  406. public override bool RequireSorting { get { return true; } }
  407. public override int Count { get { return positions.Count; } }
  408. }
  409. internal class DescendantIterator : SimpleIterator
  410. {
  411. protected int _depth;
  412. private bool _finished;
  413. public DescendantIterator (BaseIterator iter) : base (iter) {}
  414. protected DescendantIterator (DescendantIterator other) : base (other)
  415. {
  416. _depth = other._depth;
  417. _current = other._current.Clone ();
  418. }
  419. public override XPathNodeIterator Clone () { return new DescendantIterator (this); }
  420. public override bool MoveNext ()
  421. {
  422. if (_finished)
  423. return false;
  424. if (_nav.MoveToFirstChild ())
  425. {
  426. _depth ++;
  427. _pos ++;
  428. // This clone cannot be omitted
  429. _current = _nav.Clone ();
  430. return true;
  431. }
  432. while (_depth != 0)
  433. {
  434. if (_nav.MoveToNext ())
  435. {
  436. _pos ++;
  437. // This clone cannot be omitted
  438. _current = _nav.Clone ();
  439. return true;
  440. }
  441. if (!_nav.MoveToParent ()) // should NEVER fail!
  442. throw new XPathException ("There seems some bugs on the XPathNavigator implementation class.");
  443. _depth --;
  444. }
  445. _finished = true;
  446. return false;
  447. }
  448. public override bool RequireSorting { get { return false; } }
  449. }
  450. internal class DescendantOrSelfIterator : SimpleIterator
  451. {
  452. protected int _depth;
  453. private bool _finished;
  454. public DescendantOrSelfIterator (BaseIterator iter) : base (iter) {}
  455. protected DescendantOrSelfIterator (DescendantOrSelfIterator other) : base (other)
  456. {
  457. _depth = other._depth;
  458. _current = other._current.Clone ();
  459. }
  460. public override XPathNodeIterator Clone () { return new DescendantOrSelfIterator (this); }
  461. public override bool MoveNext ()
  462. {
  463. if (_finished)
  464. return false;
  465. if (_pos == 0)
  466. {
  467. // self
  468. _pos ++;
  469. // This clone cannot be omitted
  470. _current = _nav.Clone ();
  471. return true;
  472. }
  473. if (_nav.MoveToFirstChild ())
  474. {
  475. _depth ++;
  476. _pos ++;
  477. // This clone cannot be omitted
  478. _current = _nav.Clone ();
  479. return true;
  480. }
  481. while (_depth != 0)
  482. {
  483. if (_nav.MoveToNext ())
  484. {
  485. _pos ++;
  486. // This clone cannot be omitted
  487. _current = _nav.Clone ();
  488. return true;
  489. }
  490. if (!_nav.MoveToParent ()) // should NEVER fail!
  491. throw new XPathException ("There seems some bugs on the XPathNavigator implementation class.");
  492. _depth --;
  493. }
  494. _finished = true;
  495. return false;
  496. }
  497. public override bool RequireSorting { get { return false; } }
  498. }
  499. internal class FollowingIterator : SimpleIterator
  500. {
  501. private bool _finished = false;
  502. public FollowingIterator (BaseIterator iter) : base (iter) {}
  503. protected FollowingIterator (FollowingIterator other) : base (other) {}
  504. public override XPathNodeIterator Clone () { return new FollowingIterator (this); }
  505. public override bool MoveNext ()
  506. {
  507. if (_finished)
  508. return false;
  509. if (_pos == 0)
  510. {
  511. if (_nav.MoveToNext ())
  512. {
  513. _pos ++;
  514. // This clone cannot be omitted
  515. _current = _nav.Clone ();
  516. return true;
  517. } else {
  518. while (_nav.MoveToParent ()) {
  519. if (_nav.MoveToNext ()) {
  520. _pos ++;
  521. // This clone cannot be omitted
  522. _current = _nav.Clone ();
  523. return true;
  524. }
  525. }
  526. }
  527. }
  528. else
  529. {
  530. if (_nav.MoveToFirstChild ())
  531. {
  532. _pos ++;
  533. // This clone cannot be omitted
  534. _current = _nav.Clone ();
  535. return true;
  536. }
  537. do
  538. {
  539. if (_nav.MoveToNext ())
  540. {
  541. _pos ++;
  542. // This clone cannot be omitted
  543. _current = _nav.Clone ();
  544. return true;
  545. }
  546. }
  547. while (_nav.MoveToParent ());
  548. }
  549. _finished = true;
  550. return false;
  551. }
  552. public override bool RequireSorting { get { return false; } }
  553. }
  554. internal class PrecedingIterator : SimpleIterator
  555. {
  556. bool finished;
  557. bool started;
  558. XPathNavigator startPosition;
  559. public PrecedingIterator (BaseIterator iter) : base (iter)
  560. {
  561. startPosition = iter.Current.Clone ();
  562. _current = startPosition.Clone ();
  563. }
  564. protected PrecedingIterator (PrecedingIterator other) : base (other)
  565. {
  566. startPosition = other.startPosition;
  567. started = other.started;
  568. finished = other.finished;
  569. _current = other._current.Clone ();
  570. }
  571. public override XPathNodeIterator Clone () { return new PrecedingIterator (this); }
  572. public override bool MoveNext ()
  573. {
  574. if (finished)
  575. return false;
  576. if (!started) {
  577. started = true;
  578. _nav.MoveToRoot ();
  579. }
  580. bool loop = true;
  581. while (loop) {
  582. while (!_nav.MoveToFirstChild ()) {
  583. while (!_nav.MoveToNext ()) {
  584. if (!_nav.MoveToParent ()) { // Should not finish, at least before startPosition.
  585. finished = true;
  586. return false;
  587. }
  588. }
  589. break;
  590. }
  591. if (_nav.IsDescendant (startPosition))
  592. continue;
  593. loop = false;
  594. break;
  595. }
  596. if (_nav.ComparePosition (startPosition) != XmlNodeOrder.Before) {
  597. // Note that if _nav contains only 1 node, it won't be Same.
  598. finished = true;
  599. return false;
  600. } else {
  601. _pos ++;
  602. // This cannot be omitted
  603. _current = _nav.Clone ();
  604. return true;
  605. }
  606. }
  607. public override bool ReverseAxis {
  608. get { return true; }
  609. }
  610. public override bool RequireSorting { get { return true; } }
  611. }
  612. internal class NamespaceIterator : SimpleIterator
  613. {
  614. public NamespaceIterator (BaseIterator iter) : base (iter) {}
  615. protected NamespaceIterator (NamespaceIterator other) : base (other) {}
  616. public override XPathNodeIterator Clone () { return new NamespaceIterator (this); }
  617. public override bool MoveNext ()
  618. {
  619. if (_pos == 0)
  620. {
  621. if (_nav.MoveToFirstNamespace ())
  622. {
  623. _pos ++;
  624. // This clone cannot be omitted
  625. _current = _nav.Clone ();
  626. return true;
  627. }
  628. }
  629. else if (_nav.MoveToNextNamespace ())
  630. {
  631. _pos ++;
  632. // This clone cannot be omitted
  633. _current = _nav.Clone ();
  634. return true;
  635. }
  636. return false;
  637. }
  638. public override bool ReverseAxis { get { return true; } }
  639. public override bool RequireSorting { get { return false; } }
  640. }
  641. internal class AttributeIterator : SimpleIterator
  642. {
  643. public AttributeIterator (BaseIterator iter) : base (iter) {}
  644. protected AttributeIterator (AttributeIterator other) : base (other) {}
  645. public override XPathNodeIterator Clone () { return new AttributeIterator (this); }
  646. public override bool MoveNext ()
  647. {
  648. if (_pos == 0)
  649. {
  650. if (_nav.MoveToFirstAttribute ())
  651. {
  652. _pos += 1;
  653. // This clone cannot be omitted
  654. _current = _nav.Clone ();
  655. return true;
  656. }
  657. }
  658. else if (_nav.MoveToNextAttribute ())
  659. {
  660. _pos ++;
  661. // This clone cannot be omitted
  662. _current = _nav.Clone ();
  663. return true;
  664. }
  665. return false;
  666. }
  667. public override bool RequireSorting { get { return false; } }
  668. }
  669. internal class AxisIterator : BaseIterator
  670. {
  671. protected SimpleIterator _iter;
  672. protected NodeTest _test;
  673. protected int _pos;
  674. string name, ns;
  675. XPathNodeType matchType;
  676. public AxisIterator (SimpleIterator iter, NodeTest test) : base (iter)
  677. {
  678. _iter = iter;
  679. _test = test;
  680. test.GetInfo (out name, out ns, out matchType, NamespaceManager);
  681. // if (name != null)
  682. // name = Current.NameTable.Add (name);
  683. // if (ns != null)
  684. // ns = Current.NameTable.Add (ns);
  685. }
  686. protected AxisIterator (AxisIterator other) : base (other)
  687. {
  688. _iter = (SimpleIterator) other._iter.Clone ();
  689. _test = other._test;
  690. _pos = other._pos;
  691. name = other.name;
  692. ns = other.ns;
  693. matchType = other.matchType;
  694. }
  695. public override XPathNodeIterator Clone () { return new AxisIterator (this); }
  696. public override bool MoveNext ()
  697. {
  698. while (_iter.MoveNext ())
  699. {
  700. if (_test.Match (NamespaceManager, Current))
  701. {
  702. _pos ++;
  703. return true;
  704. }
  705. }
  706. return false;
  707. }
  708. public override XPathNavigator Current { get { return _iter.Current; }}
  709. public override int CurrentPosition { get { return _pos; }}
  710. bool Match ()
  711. {
  712. if (Current.NodeType != matchType && matchType != XPathNodeType.All)
  713. return false;
  714. if (ns == null)
  715. return name == null || (object)name == (object)Current.LocalName;
  716. else
  717. return (object)ns == (object)Current.NamespaceURI &&
  718. (name == null || (object)name == (object)Current.LocalName);
  719. }
  720. public override bool ReverseAxis {
  721. get { return _iter.ReverseAxis; }
  722. }
  723. public override bool RequireSorting { get { return _iter.RequireSorting; } }
  724. }
  725. internal class SlashIterator : BaseIterator
  726. {
  727. protected BaseIterator _iterLeft;
  728. protected BaseIterator _iterRight;
  729. protected NodeSet _expr;
  730. protected int _pos;
  731. ArrayList _navStore;
  732. SortedList _iterList;
  733. bool _finished;
  734. BaseIterator _nextIterRight;
  735. public SlashIterator (BaseIterator iter, NodeSet expr) : base (iter)
  736. {
  737. _iterLeft = iter;
  738. _expr = expr;
  739. }
  740. protected SlashIterator (SlashIterator other) : base (other)
  741. {
  742. _iterLeft = (BaseIterator) other._iterLeft.Clone ();
  743. if (other._iterRight != null)
  744. _iterRight = (BaseIterator) other._iterRight.Clone ();
  745. _expr = other._expr;
  746. _pos = other._pos;
  747. if (other._iterList != null)
  748. _iterList = (SortedList) other._iterList.Clone ();
  749. if (other._navStore != null)
  750. _navStore = (ArrayList) other._navStore.Clone ();
  751. _finished = other._finished;
  752. if (other._nextIterRight != null)
  753. _nextIterRight = (BaseIterator) other._nextIterRight.Clone ();
  754. }
  755. public override XPathNodeIterator Clone () { return new SlashIterator (this); }
  756. public override bool MoveNext ()
  757. {
  758. if (_finished)
  759. return false;
  760. if (RequireSorting) {
  761. if (_pos <= 0) {
  762. CollectResults ();
  763. if (_navStore.Count == 0) {
  764. _finished = true;
  765. return false;
  766. }
  767. }
  768. _pos++;
  769. if (_navStore.Count < _pos) {
  770. _finished = true;
  771. _pos--;
  772. return false;
  773. }
  774. while (_navStore.Count > _pos) {
  775. if (((XPathNavigator) _navStore [_pos]).ComparePosition (
  776. (XPathNavigator) _navStore [_pos - 1]) == XmlNodeOrder.Same)
  777. _navStore.RemoveAt (_pos);
  778. else
  779. break;
  780. }
  781. return true;
  782. } else {
  783. if (_iterRight == null) { // First time
  784. if (!_iterLeft.MoveNext ())
  785. return false;
  786. _iterRight = _expr.EvaluateNodeSet (_iterLeft);
  787. _iterList = new SortedList (XPathIteratorComparer.Instance);
  788. }
  789. while (true) {
  790. while (!_iterRight.MoveNext ()) {
  791. if (_iterList.Count > 0) {
  792. int last = _iterList.Count - 1;
  793. BaseIterator tmpIter = (BaseIterator) _iterList.GetByIndex (last);
  794. _iterList.RemoveAt (last);
  795. switch (tmpIter.Current.ComparePosition (_iterRight.Current)) {
  796. case XmlNodeOrder.Same:
  797. case XmlNodeOrder.Before:
  798. _iterRight = tmpIter;
  799. continue;
  800. default:
  801. _iterRight = tmpIter;
  802. break;
  803. }
  804. break;
  805. } else if (_nextIterRight != null) {
  806. _iterRight = _nextIterRight;
  807. _nextIterRight = null;
  808. break;
  809. } else if (!_iterLeft.MoveNext ()) {
  810. _finished = true;
  811. return false;
  812. }
  813. else
  814. _iterRight = _expr.EvaluateNodeSet (_iterLeft);
  815. }
  816. bool loop = true;
  817. while (loop) {
  818. loop = false;
  819. if (_nextIterRight == null) {
  820. bool noMoreNext = false;
  821. while (_nextIterRight == null || !_nextIterRight.MoveNext ()) {
  822. if(_iterLeft.MoveNext ())
  823. _nextIterRight = _expr.EvaluateNodeSet (_iterLeft);
  824. else {
  825. noMoreNext = true;
  826. break;
  827. }
  828. }
  829. if (noMoreNext)
  830. _nextIterRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
  831. }
  832. if (_nextIterRight != null) {
  833. switch (_iterRight.Current.ComparePosition (_nextIterRight.Current)) {
  834. case XmlNodeOrder.After:
  835. _iterList.Add (_iterList.Count, _iterRight);
  836. _iterRight = _nextIterRight;
  837. _nextIterRight = null;
  838. loop = true;
  839. break;
  840. case XmlNodeOrder.Same:
  841. if (!_nextIterRight.MoveNext ())
  842. _nextIterRight = null;
  843. else {
  844. int last = _iterList.Count;
  845. if (last > 0) {
  846. _iterList.Add (last, _nextIterRight);
  847. _nextIterRight = (BaseIterator) _iterList.GetByIndex (last);
  848. _iterList.RemoveAt (last);
  849. }
  850. }
  851. loop = true;
  852. break;
  853. }
  854. }
  855. }
  856. _pos ++;
  857. return true;
  858. }
  859. }
  860. }
  861. private void CollectResults ()
  862. {
  863. if (_navStore != null)
  864. return;
  865. _navStore = new ArrayList ();
  866. while (true) {
  867. while (_iterRight == null || !_iterRight.MoveNext ()) {
  868. if (!_iterLeft.MoveNext ()) {
  869. _navStore.Sort (XPathNavigatorComparer.Instance);
  870. return;
  871. }
  872. _iterRight = _expr.EvaluateNodeSet (_iterLeft);
  873. }
  874. XPathNavigator nav = _iterRight.Current;
  875. _navStore.Add (_needClone ? nav.Clone () : nav);
  876. }
  877. }
  878. public override XPathNavigator Current {
  879. get {
  880. if (_pos <= 0) return null;
  881. if (RequireSorting) {
  882. return (XPathNavigator) _navStore [_pos - 1];
  883. } else {
  884. return _iterRight.Current;
  885. }
  886. }
  887. }
  888. public override int CurrentPosition { get { return _pos; }}
  889. public override bool RequireSorting {
  890. get {
  891. return _iterLeft.RequireSorting || _expr.RequireSorting;
  892. }
  893. }
  894. public override int Count { get { return _navStore == null ? base.Count : _navStore.Count; } }
  895. }
  896. internal class PredicateIterator : BaseIterator
  897. {
  898. protected BaseIterator _iter;
  899. protected Expression _pred;
  900. protected int _pos;
  901. protected XPathResultType resType;
  902. public PredicateIterator (BaseIterator iter, Expression pred) : base (iter)
  903. {
  904. _iter = iter;
  905. _pred = pred;
  906. resType = pred.GetReturnType (iter);
  907. }
  908. protected PredicateIterator (PredicateIterator other) : base (other)
  909. {
  910. _iter = (BaseIterator) other._iter.Clone ();
  911. _pred = other._pred;
  912. _pos = other._pos;
  913. resType = other.resType;
  914. }
  915. public override XPathNodeIterator Clone () { return new PredicateIterator (this); }
  916. public override bool MoveNext ()
  917. {
  918. while (_iter.MoveNext ())
  919. {
  920. switch (resType) {
  921. case XPathResultType.Number:
  922. if (_pred.EvaluateNumber (_iter) != _iter.ComparablePosition)
  923. continue;
  924. break;
  925. case XPathResultType.Any: {
  926. object result = _pred.Evaluate (_iter);
  927. if (result is double)
  928. {
  929. if ((double) result != _iter.ComparablePosition)
  930. continue;
  931. }
  932. else if (!XPathFunctions.ToBoolean (result))
  933. continue;
  934. }
  935. break;
  936. default:
  937. if (!_pred.EvaluateBoolean (_iter))
  938. continue;
  939. break;
  940. }
  941. _pos ++;
  942. return true;
  943. }
  944. return false;
  945. }
  946. public override XPathNavigator Current { get { return _iter.Current; }}
  947. public override int CurrentPosition { get { return _pos; }}
  948. public override bool ReverseAxis {
  949. get { return _iter.ReverseAxis; }
  950. }
  951. public override bool RequireSorting { get { return true; } }
  952. }
  953. internal class EnumeratorIterator : BaseIterator
  954. {
  955. protected IEnumerator _enum;
  956. protected int _pos;
  957. bool _requireSorting;
  958. public EnumeratorIterator (BaseIterator iter, IEnumerator enumerator, bool requireSorting) : base (iter)
  959. {
  960. if (!(enumerator is ICloneable))
  961. throw new ArgumentException ("Target enumerator must be cloneable.");
  962. _enum = enumerator;
  963. _requireSorting = requireSorting;
  964. }
  965. public EnumeratorIterator (IEnumerator enumerator, XmlNamespaceManager nsm, bool requireSorting) : base (nsm)
  966. {
  967. if (!(enumerator is ICloneable))
  968. throw new ArgumentException ("Target enumerator must be cloneable.");
  969. _enum = enumerator;
  970. _requireSorting = requireSorting;
  971. }
  972. protected EnumeratorIterator (EnumeratorIterator other) : base (other)
  973. {
  974. ICloneable enumClone = other._enum as ICloneable;
  975. _enum = (IEnumerator) enumClone.Clone ();
  976. _pos = other._pos;
  977. _requireSorting = other._requireSorting;
  978. }
  979. public override XPathNodeIterator Clone () { return new EnumeratorIterator (this); }
  980. public override bool MoveNext ()
  981. {
  982. if (!_enum.MoveNext ())
  983. return false;
  984. _pos++;
  985. return true;
  986. }
  987. public override XPathNavigator Current { get { return (XPathNavigator) _enum.Current; }}
  988. public override int CurrentPosition { get { return _pos; }}
  989. public override bool RequireSorting { get { return _requireSorting; } }
  990. }
  991. internal class ListIterator : BaseIterator
  992. {
  993. protected IList _list;
  994. protected int _pos;
  995. bool _requireSorting;
  996. public ListIterator (BaseIterator iter, IList list, bool requireSorting) : base (iter)
  997. {
  998. if (!(list is ICloneable))
  999. throw new ArgumentException ("Target enumerator must be cloneable.");
  1000. _list = list;
  1001. _requireSorting = requireSorting;
  1002. }
  1003. public ListIterator (IList list, XmlNamespaceManager nsm, bool requireSorting) : base (nsm)
  1004. {
  1005. if (!(list is ICloneable))
  1006. throw new ArgumentException ("Target enumerator must be cloneable.");
  1007. _list = list;
  1008. _requireSorting = requireSorting;
  1009. }
  1010. protected ListIterator (ListIterator other) : base (other)
  1011. {
  1012. ICloneable listClone = other._list as ICloneable;
  1013. _list = (IList) listClone.Clone ();
  1014. _pos = other._pos;
  1015. _requireSorting = other._requireSorting;
  1016. }
  1017. public override XPathNodeIterator Clone () { return new ListIterator (this); }
  1018. public override bool MoveNext ()
  1019. {
  1020. if (_pos >= _list.Count)
  1021. return false;
  1022. _pos++;
  1023. return true;
  1024. }
  1025. public override XPathNavigator Current {
  1026. get {
  1027. if (_list.Count == 0)
  1028. return null;
  1029. return (XPathNavigator) _list [_pos - 1];
  1030. }
  1031. }
  1032. public override int CurrentPosition { get { return _pos; }}
  1033. public override bool RequireSorting { get { return _requireSorting; } }
  1034. public override int Count { get { return _list.Count; } }
  1035. }
  1036. internal class UnionIterator : BaseIterator
  1037. {
  1038. protected BaseIterator _left, _right;
  1039. private int _pos;
  1040. private bool keepLeft;
  1041. private bool keepRight;
  1042. private bool useRight;
  1043. public UnionIterator (BaseIterator iter, BaseIterator left, BaseIterator right) : base (iter)
  1044. {
  1045. _left = left;
  1046. _right = right;
  1047. }
  1048. protected UnionIterator (UnionIterator other) : base (other)
  1049. {
  1050. _left = (BaseIterator) other._left.Clone ();
  1051. _right = (BaseIterator) other._right.Clone ();
  1052. _pos = other._pos;
  1053. keepLeft = other.keepLeft;
  1054. keepRight = other.keepRight;
  1055. useRight = other.useRight;
  1056. }
  1057. public override XPathNodeIterator Clone () { return new UnionIterator (this); }
  1058. public override bool MoveNext ()
  1059. {
  1060. if (!keepLeft)
  1061. keepLeft = _left.MoveNext ();
  1062. if (!keepRight)
  1063. keepRight = _right.MoveNext ();
  1064. if (!keepLeft && !keepRight)
  1065. return false;
  1066. _pos ++;
  1067. if (!keepRight) {
  1068. keepLeft = useRight = false;
  1069. return true;
  1070. } else if (!keepLeft) {
  1071. keepRight = false;
  1072. useRight = true;
  1073. return true;
  1074. }
  1075. switch (_left.Current.ComparePosition (_right.Current)) {
  1076. case XmlNodeOrder.Same:
  1077. // consume both. i.e. don't output duplicate result.
  1078. keepLeft = keepRight = false;
  1079. useRight = true;
  1080. return true;
  1081. case XmlNodeOrder.Before:
  1082. case XmlNodeOrder.Unknown: // Maybe happen because of "document(a) | document(b)"
  1083. keepLeft = useRight = false;
  1084. return true;
  1085. case XmlNodeOrder.After:
  1086. keepRight = false;
  1087. useRight = true;
  1088. return true;
  1089. default:
  1090. throw new InvalidOperationException ("Should not happen.");
  1091. }
  1092. }
  1093. public override XPathNavigator Current
  1094. {
  1095. get
  1096. {
  1097. if (_pos == 0)
  1098. return null;
  1099. if (useRight)
  1100. return _right.Current;
  1101. else
  1102. return _left.Current;
  1103. }
  1104. }
  1105. public override int CurrentPosition { get { return _pos; }}
  1106. public override bool RequireSorting { get { return _left.RequireSorting || _right.RequireSorting; } }
  1107. }
  1108. }