Iterator.cs 31 KB

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