XPathSequence.cs 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490
  1. //
  2. // XPathSequence.cs - represents XPath sequence iterator
  3. //
  4. // Author:
  5. // Atsushi Enomoto <[email protected]>
  6. //
  7. //
  8. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. #if NET_2_0
  30. using System;
  31. using System.Collections;
  32. using System.Xml;
  33. using System.Xml.Schema;
  34. using System.Xml.Query;
  35. using System.Xml.XPath;
  36. namespace Mono.Xml.XPath2
  37. {
  38. public abstract class XPathSequence : IEnumerable, ICloneable
  39. {
  40. XQueryContext ctx;
  41. int countCache = -1;
  42. int position = 0;
  43. internal XPathSequence (XQueryContext ctx)
  44. {
  45. this.ctx = ctx;
  46. }
  47. internal XPathSequence (XPathSequence original)
  48. {
  49. ctx = original.ctx;
  50. position = original.position;
  51. }
  52. internal XQueryContext Context {
  53. get { return ctx; }
  54. }
  55. public virtual int Count {
  56. get {
  57. if (countCache >= 0)
  58. return countCache;
  59. XPathSequence clone = Clone ();
  60. while (clone.MoveNext ())
  61. ;
  62. countCache = clone.Position;
  63. return countCache;
  64. }
  65. }
  66. public XPathItem Current {
  67. get {
  68. if (Position == 0)
  69. throw new InvalidOperationException ("XQuery internal error (should not happen)");
  70. return CurrentCore;
  71. }
  72. }
  73. public abstract XPathItem CurrentCore { get; }
  74. // Returns 0 if not started, otherwise returns XPath positional integer.
  75. public int Position {
  76. get { return position; }
  77. }
  78. public bool MoveNext ()
  79. {
  80. if (!MoveNextCore ())
  81. return false;
  82. position++;
  83. return true;
  84. }
  85. protected abstract bool MoveNextCore ();
  86. public abstract XPathSequence Clone ();
  87. object ICloneable.Clone ()
  88. {
  89. return this.Clone ();
  90. }
  91. public virtual IEnumerator GetEnumerator ()
  92. {
  93. while (MoveNext ())
  94. yield return CurrentCore;
  95. }
  96. }
  97. // empty iterator (still required since it contains XQueryContext)
  98. class XPathEmptySequence : XPathSequence
  99. {
  100. internal XPathEmptySequence (XQueryContext ctx)
  101. : base (ctx)
  102. {
  103. }
  104. public override int Count {
  105. get { return 0; }
  106. }
  107. protected override bool MoveNextCore ()
  108. {
  109. return false;
  110. }
  111. public override XPathItem CurrentCore {
  112. get { throw new InvalidOperationException ("Should not happen. In XPathEmptySequence.Current."); }
  113. }
  114. // Don't return clone. It's waste of resource.
  115. public override XPathSequence Clone ()
  116. {
  117. return this;
  118. }
  119. }
  120. // single item iterator
  121. internal class SingleItemIterator : XPathSequence
  122. {
  123. XPathItem item;
  124. XPathItem current;
  125. public SingleItemIterator (XPathItem item, XPathSequence iter)
  126. : this (item, iter.Context)
  127. {
  128. }
  129. // for XQuery execution start point
  130. internal SingleItemIterator (XPathItem item, XQueryContext ctx)
  131. : base (ctx)
  132. {
  133. this.item = item;
  134. }
  135. private SingleItemIterator (SingleItemIterator other)
  136. : base (other)
  137. {
  138. this.item = other.item;
  139. this.current = other.current;
  140. }
  141. public override XPathSequence Clone ()
  142. {
  143. return new SingleItemIterator (this);
  144. }
  145. protected override bool MoveNextCore ()
  146. {
  147. if (current == null) {
  148. current = item;
  149. return true;
  150. }
  151. return false;
  152. }
  153. public override XPathItem CurrentCore {
  154. get {
  155. return current;
  156. }
  157. }
  158. }
  159. // RangeExpr iterator
  160. internal class IntegerRangeIterator : XPathSequence
  161. {
  162. static XmlSchemaSimpleType intType = XmlSchemaType.GetBuiltInSimpleType (new XmlQualifiedName ("int", XmlSchema.Namespace));
  163. int start;
  164. int end;
  165. int next;
  166. XPathItem current;
  167. public IntegerRangeIterator (XPathSequence iter, int start, int end)
  168. : base (iter.Context)
  169. {
  170. this.start = start;
  171. this.end = end;
  172. }
  173. private IntegerRangeIterator (IntegerRangeIterator other)
  174. : base (other)
  175. {
  176. this.start = other.start;
  177. this.end = other.end;
  178. this.next = other.next;
  179. this.current = other.current;
  180. }
  181. public override XPathSequence Clone ()
  182. {
  183. return new IntegerRangeIterator (this);
  184. }
  185. protected override bool MoveNextCore ()
  186. {
  187. if (current == null)
  188. next = start;
  189. if (next > end)
  190. return false;
  191. current = new XPathAtomicValue (next++, intType);
  192. return true;
  193. }
  194. public override XPathItem CurrentCore {
  195. get {
  196. return current;
  197. }
  198. }
  199. }
  200. // Slash iterator
  201. // <copy original='System.Xml.XPath/Iterator.cs,
  202. // System.Xml.XPath/XPathComparer.cs'>
  203. internal class PathStepIterator : XPathSequence
  204. {
  205. XPathSequence left;
  206. XPathSequence right;
  207. PathStepExpr step;
  208. ArrayList nodeStore;
  209. SortedList storedIterators;
  210. bool finished;
  211. XPathSequence nextRight;
  212. public PathStepIterator (XPathSequence iter, PathStepExpr source)
  213. : base (iter.Context)
  214. {
  215. left = iter;
  216. step = source;
  217. }
  218. private PathStepIterator (PathStepIterator other)
  219. : base (other)
  220. {
  221. left = other.left.Clone ();
  222. step = other.step;
  223. if (other.right != null)
  224. right = other.right.Clone ();
  225. if (other.nodeStore != null)
  226. nodeStore = (ArrayList) other.nodeStore.Clone ();
  227. if (other.storedIterators != null)
  228. storedIterators = (SortedList) other.storedIterators.Clone ();
  229. if (other.nextRight != null)
  230. nextRight = other.nextRight.Clone ();
  231. }
  232. public override XPathSequence Clone ()
  233. {
  234. return new PathStepIterator (this);
  235. }
  236. protected override bool MoveNextCore ()
  237. {
  238. if (finished)
  239. return false;
  240. // if (RequireSorting) {
  241. if (step.RequireSorting) {
  242. // Mainly '//' ('/descendant-or-self::node()/')
  243. if (nodeStore == null) {
  244. CollectResults ();
  245. if (nodeStore.Count == 0) {
  246. finished = true;
  247. return false;
  248. }
  249. }
  250. if (nodeStore.Count == Position) {
  251. finished = true;
  252. return false;
  253. }
  254. while (nodeStore.Count > Position) {
  255. if (((XPathNavigator) nodeStore [Position]).ComparePosition (
  256. (XPathNavigator) nodeStore [Position - 1]) == XmlNodeOrder.Same)
  257. nodeStore.RemoveAt (Position);
  258. else
  259. break;
  260. }
  261. return true;
  262. } else { // Sorting not required
  263. if (right == null) { // First time
  264. if (!left.MoveNext ())
  265. return false;
  266. right = step.Next.Evaluate (left);
  267. storedIterators = new SortedList (XPathSequenceComparer.Instance);
  268. }
  269. while (true) {
  270. while (!right.MoveNext ()) {
  271. if (storedIterators.Count > 0) {
  272. int last = storedIterators.Count - 1;
  273. XPathSequence tmpIter = (XPathSequence) storedIterators.GetByIndex (last);
  274. storedIterators.RemoveAt (last);
  275. switch (((XPathNavigator) tmpIter.Current).ComparePosition ((XPathNavigator) right.Current)) {
  276. case XmlNodeOrder.Same:
  277. case XmlNodeOrder.Before:
  278. right = tmpIter;
  279. continue;
  280. default:
  281. right = tmpIter;
  282. break;
  283. }
  284. break;
  285. } else if (nextRight != null) {
  286. right = nextRight;
  287. nextRight = null;
  288. break;
  289. } else if (!left.MoveNext ()) {
  290. finished = true;
  291. return false;
  292. }
  293. else
  294. right = step.Next.Evaluate (left);
  295. }
  296. bool loop = true;
  297. while (loop) {
  298. loop = false;
  299. if (nextRight == null) {
  300. bool noMoreNext = false;
  301. while (nextRight == null || !nextRight.MoveNext ()) {
  302. if(left.MoveNext ())
  303. nextRight = step.Next.Evaluate (left);
  304. else {
  305. noMoreNext = true;
  306. break;
  307. }
  308. }
  309. if (noMoreNext)
  310. nextRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
  311. }
  312. if (nextRight != null) {
  313. switch (((XPathNavigator) right.Current).ComparePosition ((XPathNavigator) nextRight.Current)) {
  314. case XmlNodeOrder.After:
  315. storedIterators.Add (storedIterators.Count, right);
  316. right = nextRight;
  317. nextRight = null;
  318. loop = true;
  319. break;
  320. case XmlNodeOrder.Same:
  321. if (!nextRight.MoveNext ())
  322. nextRight = null;
  323. else {
  324. int last = storedIterators.Count;
  325. if (last > 0) {
  326. storedIterators.Add (last, nextRight);
  327. nextRight = (XPathSequence) storedIterators.GetByIndex (last);
  328. storedIterators.RemoveAt (last);
  329. }
  330. }
  331. loop = true;
  332. break;
  333. }
  334. }
  335. }
  336. return true;
  337. }
  338. }
  339. }
  340. private void CollectResults ()
  341. {
  342. if (nodeStore != null)
  343. return;
  344. nodeStore = new ArrayList ();
  345. while (true) {
  346. while (right == null || !right.MoveNext ()) {
  347. if (!left.MoveNext ()) {
  348. nodeStore.Sort (XPathNavigatorComparer2.Instance);
  349. return;
  350. }
  351. right = step.Next.Evaluate (left);
  352. }
  353. XPathNavigator nav = (XPathNavigator) right.Current;
  354. nodeStore.Add (nav);
  355. }
  356. }
  357. public override XPathItem CurrentCore {
  358. get {
  359. if (Position <= 0) return null;
  360. // if (RequireSorting) {
  361. if (step.RequireSorting) {
  362. return (XPathNavigator) nodeStore [Position - 1];
  363. } else {
  364. return right.Current;
  365. }
  366. }
  367. }
  368. /*
  369. public override bool RequireSorting {
  370. get {
  371. return left.RequireSorting || step.Next.RequireSorting;
  372. }
  373. }
  374. */
  375. public override int Count {
  376. get {
  377. if (nodeStore == null)
  378. return base.Count;
  379. else
  380. return nodeStore.Count;
  381. }
  382. }
  383. internal class XPathSequenceComparer : IComparer
  384. {
  385. public static XPathSequenceComparer Instance = new XPathSequenceComparer ();
  386. private XPathSequenceComparer ()
  387. {
  388. }
  389. public int Compare (object o1, object o2)
  390. {
  391. XPathSequence nav1 = o1 as XPathSequence;
  392. XPathSequence nav2 = o2 as XPathSequence;
  393. if (nav1 == null)
  394. return -1;
  395. if (nav2 == null)
  396. return 1;
  397. switch (((XPathNavigator) nav1.Current).ComparePosition ((XPathNavigator) nav2.Current)) {
  398. case XmlNodeOrder.Same:
  399. return 0;
  400. case XmlNodeOrder.After:
  401. return -1;
  402. default:
  403. return 1;
  404. }
  405. }
  406. }
  407. internal class XPathNavigatorComparer2 : IComparer
  408. {
  409. public static XPathNavigatorComparer2 Instance = new XPathNavigatorComparer2 ();
  410. private XPathNavigatorComparer2 ()
  411. {
  412. }
  413. public int Compare (object o1, object o2)
  414. {
  415. XPathNavigator nav1 = o1 as XPathNavigator;
  416. XPathNavigator nav2 = o2 as XPathNavigator;
  417. if (nav1 == null)
  418. return -1;
  419. if (nav2 == null)
  420. return 1;
  421. switch (nav1.ComparePosition (nav2)) {
  422. case XmlNodeOrder.Same:
  423. return 0;
  424. case XmlNodeOrder.After:
  425. return 1;
  426. default:
  427. return -1;
  428. }
  429. }
  430. }
  431. }
  432. // </copy>
  433. // Filter step iterator
  434. internal class FilteredIterator : XPathSequence
  435. {
  436. XPathSequence left;
  437. PredicateList filter;
  438. public FilteredIterator (XPathSequence iter, FilterStepExpr source)
  439. : base (iter.Context)
  440. {
  441. left = source.Expr.Evaluate (iter);
  442. filter = source.Predicates;
  443. }
  444. private FilteredIterator (FilteredIterator other)
  445. : base (other)
  446. {
  447. left = other.left.Clone ();
  448. filter = other.filter;
  449. }
  450. public override XPathSequence Clone ()
  451. {
  452. return new FilteredIterator (this);
  453. }
  454. protected override bool MoveNextCore ()
  455. {
  456. while (left.MoveNext ()) {
  457. bool skipThisItem = false;
  458. // Examine all filters
  459. foreach (ExprSequence expr in filter) {
  460. bool doesntPass = true;
  461. // Treat as OK if any of expr passed.
  462. // FIXME: handle numeric predicate.
  463. foreach (ExprSingle single in expr) {
  464. if (single.EvaluateAsBoolean (left)) {
  465. doesntPass = false;
  466. break;
  467. }
  468. }
  469. if (doesntPass) {
  470. skipThisItem = true;
  471. break;
  472. }
  473. }
  474. if (skipThisItem)
  475. continue;
  476. return true;
  477. }
  478. return false;
  479. }
  480. public override XPathItem CurrentCore {
  481. get { return left.Current; }
  482. }
  483. }
  484. // AxisIterator
  485. internal class AxisIterator : XPathSequence
  486. {
  487. XPathSequence iter;
  488. AxisStepExpr source;
  489. public AxisIterator (XPathSequence iter, AxisStepExpr source)
  490. : base (iter.Context)
  491. {
  492. this.iter = iter;
  493. this.source = source;
  494. }
  495. private AxisIterator (AxisIterator other)
  496. : base (other)
  497. {
  498. iter = other.iter.Clone ();
  499. source = other.source;
  500. }
  501. public override XPathSequence Clone ()
  502. {
  503. return new AxisIterator (this);
  504. }
  505. protected override bool MoveNextCore ()
  506. {
  507. while (iter.MoveNext ()) {
  508. if (source.Matches (iter.Current as XPathNavigator))
  509. return true;
  510. }
  511. return false;
  512. }
  513. public override XPathItem CurrentCore {
  514. get { return iter.Current; }
  515. }
  516. }
  517. internal abstract class NodeIterator : XPathSequence
  518. {
  519. XPathNavigator node;
  520. XPathNavigator current;
  521. public NodeIterator (XPathSequence iter)
  522. : base (iter.Context)
  523. {
  524. // XPathItem item = iter.Context.CurrentItem;
  525. XPathItem item = iter.Current;
  526. node = item as XPathNavigator;
  527. if (node == null)
  528. throw new XmlQueryException (String.Format ("Current item is expected to be a node, but it is {0} ({1}).", item.XmlType.QualifiedName, item.XmlType.TypeCode));
  529. node = node.Clone ();
  530. }
  531. internal NodeIterator (NodeIterator other, bool cloneFlag)
  532. : base (other)
  533. {
  534. node = other.node.Clone ();
  535. }
  536. internal XPathNavigator Node {
  537. get { return node; }
  538. }
  539. protected override bool MoveNextCore ()
  540. {
  541. if (!base.MoveNext ())
  542. return false;
  543. current = null;
  544. return true;
  545. }
  546. public override XPathItem CurrentCore {
  547. get {
  548. if (current == null)
  549. current = node.Clone ();
  550. return current;
  551. }
  552. }
  553. public virtual bool ReverseAxis {
  554. get { return false; }
  555. }
  556. // public override bool RequireSorting {
  557. // get { return ReverseAxis; }
  558. // }
  559. }
  560. // <copy original='System.Xml.XPath/Iterator.cs'>
  561. internal class ParentIterator : NodeIterator
  562. {
  563. public ParentIterator (XPathSequence iter)
  564. : base (iter)
  565. {
  566. }
  567. private ParentIterator (ParentIterator other, bool cloneFlag)
  568. : base (other, true)
  569. {
  570. }
  571. public override XPathSequence Clone ()
  572. {
  573. return new ParentIterator (this, true);
  574. }
  575. protected override bool MoveNextCore ()
  576. {
  577. if (Position == 0 && Node.MoveToParent ())
  578. return true;
  579. return false;
  580. }
  581. public override bool ReverseAxis {
  582. get { return true; }
  583. }
  584. }
  585. internal class ChildIterator : NodeIterator
  586. {
  587. public ChildIterator (XPathSequence iter)
  588. : base (iter)
  589. {
  590. }
  591. private ChildIterator (ChildIterator other, bool cloneFlag)
  592. : base (other, true)
  593. {
  594. }
  595. public override XPathSequence Clone ()
  596. {
  597. return new ChildIterator (this, true);
  598. }
  599. protected override bool MoveNextCore ()
  600. {
  601. if (Position == 0)
  602. return Node.MoveToFirstChild ();
  603. else
  604. return Node.MoveToNext ();
  605. }
  606. }
  607. internal class FollowingSiblingIterator : NodeIterator
  608. {
  609. public FollowingSiblingIterator (XPathSequence iter)
  610. : base (iter)
  611. {
  612. }
  613. private FollowingSiblingIterator (FollowingSiblingIterator other, bool cloneFlag)
  614. : base (other, true)
  615. {
  616. }
  617. public override XPathSequence Clone ()
  618. {
  619. return new FollowingSiblingIterator (this, true);
  620. }
  621. protected override bool MoveNextCore ()
  622. {
  623. return Node.MoveToNext ();
  624. }
  625. }
  626. internal class PrecedingSiblingIterator : NodeIterator
  627. {
  628. bool finished;
  629. bool started;
  630. XPathNavigator startPosition;
  631. public PrecedingSiblingIterator (XPathSequence iter)
  632. : base (iter)
  633. {
  634. startPosition = Node.Clone ();
  635. }
  636. private PrecedingSiblingIterator (PrecedingSiblingIterator other, bool cloneFlag)
  637. : base (other, true)
  638. {
  639. startPosition = other.startPosition;
  640. started = other.started;
  641. finished = other.finished;
  642. }
  643. public override XPathSequence Clone ()
  644. {
  645. return new PrecedingSiblingIterator (this, true);
  646. }
  647. protected override bool MoveNextCore ()
  648. {
  649. if (finished)
  650. return false;
  651. if (!started) {
  652. started = true;
  653. Node.MoveToFirst ();
  654. } else {
  655. Node.MoveToNext ();
  656. }
  657. if (Node.ComparePosition (startPosition) == XmlNodeOrder.Same) {
  658. finished = true;
  659. return false;
  660. }
  661. else
  662. return true;
  663. }
  664. public override bool ReverseAxis {
  665. get { return true; }
  666. }
  667. }
  668. internal class AncestorIterator : NodeIterator
  669. {
  670. bool finished;
  671. ArrayList nodes = new ArrayList ();
  672. public AncestorIterator (XPathSequence iter)
  673. : base (iter)
  674. {
  675. }
  676. private AncestorIterator (AncestorIterator other, bool cloneFlag)
  677. : base (other, true)
  678. {
  679. finished = other.finished;
  680. nodes = other.nodes;
  681. }
  682. public override XPathSequence Clone ()
  683. {
  684. return new AncestorIterator (this, true);
  685. }
  686. protected override bool MoveNextCore ()
  687. {
  688. if (finished)
  689. return false;
  690. if (nodes != null) {
  691. nodes = new ArrayList ();
  692. while (Node.MoveToParent () && Node.NodeType != XPathNodeType.Root)
  693. nodes.Add (Node.Clone ());
  694. nodes.Reverse ();
  695. }
  696. if (nodes.Count >= Position)
  697. return false;
  698. Node.MoveTo (nodes [Position] as XPathNavigator);
  699. return true;
  700. }
  701. public override bool ReverseAxis {
  702. get { return true; }
  703. }
  704. public override int Count {
  705. get {
  706. if (Position == 0)
  707. return base.Count;
  708. return nodes.Count;
  709. }
  710. }
  711. }
  712. internal class AncestorOrSelfIterator : NodeIterator
  713. {
  714. bool finished;
  715. ArrayList nodes = new ArrayList ();
  716. public AncestorOrSelfIterator (XPathSequence iter)
  717. : base (iter)
  718. {
  719. }
  720. private AncestorOrSelfIterator (AncestorOrSelfIterator other, bool cloneFlag)
  721. : base (other, true)
  722. {
  723. finished = other.finished;
  724. nodes = other.nodes;
  725. }
  726. public override XPathSequence Clone ()
  727. {
  728. return new AncestorOrSelfIterator (this, true);
  729. }
  730. protected override bool MoveNextCore ()
  731. {
  732. if (finished)
  733. return false;
  734. if (nodes != null) {
  735. nodes = new ArrayList ();
  736. do {
  737. nodes.Add (Node.Clone ());
  738. } while (Node.MoveToParent () && Node.NodeType != XPathNodeType.Root);
  739. nodes.Reverse ();
  740. }
  741. if (nodes.Count >= Position)
  742. return false;
  743. Node.MoveTo (nodes [Position] as XPathNavigator);
  744. return true;
  745. }
  746. public override bool ReverseAxis {
  747. get { return true; }
  748. }
  749. public override int Count {
  750. get {
  751. if (Position == 0)
  752. return base.Count;
  753. return nodes.Count;
  754. }
  755. }
  756. }
  757. internal class DescendantIterator : NodeIterator
  758. {
  759. private int depth;
  760. private bool finished;
  761. public DescendantIterator (XPathSequence iter)
  762. : base (iter)
  763. {
  764. }
  765. private DescendantIterator (DescendantIterator other, bool cloneFlag)
  766. : base (other, true)
  767. {
  768. finished = other.finished;
  769. depth = other.depth;
  770. }
  771. public override XPathSequence Clone ()
  772. {
  773. return new DescendantIterator (this, true);
  774. }
  775. protected override bool MoveNextCore ()
  776. {
  777. if (finished)
  778. return false;
  779. if (Node.MoveToFirstChild ()) {
  780. depth ++;
  781. return true;
  782. }
  783. while (depth != 0) {
  784. if (Node.MoveToNext ())
  785. return true;
  786. if (!Node.MoveToParent ()) // should NEVER fail!
  787. throw new XmlQueryException ("There seems some bugs on the XPathNavigator implementation class.");
  788. depth --;
  789. }
  790. finished = true;
  791. return false;
  792. }
  793. }
  794. internal class DescendantOrSelfIterator : NodeIterator
  795. {
  796. protected int depth;
  797. private bool finished;
  798. public DescendantOrSelfIterator (XPathSequence iter)
  799. : base (iter)
  800. {
  801. }
  802. protected DescendantOrSelfIterator (DescendantOrSelfIterator other, bool cloneFlag)
  803. : base (other, true)
  804. {
  805. depth = other.depth;
  806. finished = other.finished;
  807. }
  808. public override XPathSequence Clone ()
  809. {
  810. return new DescendantOrSelfIterator (this, true);
  811. }
  812. protected override bool MoveNextCore ()
  813. {
  814. if (finished)
  815. return false;
  816. if (Position == 0)
  817. return true; // Self
  818. if (Node.MoveToFirstChild ()) {
  819. depth ++;
  820. return true;
  821. }
  822. while (depth != 0) {
  823. if (Node.MoveToNext ())
  824. return true;
  825. if (!Node.MoveToParent ()) // should NEVER fail!
  826. throw new XmlQueryException ("There seems some bugs on the XPathNavigator implementation class.");
  827. depth --;
  828. }
  829. finished = true;
  830. return false;
  831. }
  832. }
  833. internal class FollowingIterator : NodeIterator
  834. {
  835. private bool finished;
  836. public FollowingIterator (XPathSequence iter)
  837. : base (iter)
  838. {
  839. }
  840. protected FollowingIterator (FollowingIterator other, bool cloneFlag)
  841. : base (other, true)
  842. {
  843. finished = other.finished;
  844. }
  845. public override XPathSequence Clone ()
  846. {
  847. return new FollowingIterator (this, true);
  848. }
  849. protected override bool MoveNextCore ()
  850. {
  851. if (finished)
  852. return false;
  853. if (Position == 0) {
  854. // At first, it should not iterate children.
  855. if (Node.MoveToNext ())
  856. return true;
  857. else {
  858. while (Node.MoveToParent ())
  859. if (Node.MoveToNext ())
  860. return true;
  861. }
  862. } else {
  863. if (Node.MoveToFirstChild ())
  864. return true;
  865. do {
  866. if (Node.MoveToNext ())
  867. return true;
  868. } while (Node.MoveToParent ());
  869. }
  870. finished = true;
  871. return false;
  872. }
  873. }
  874. internal class PrecedingIterator : NodeIterator
  875. {
  876. bool finished;
  877. bool started;
  878. XPathNavigator startPosition;
  879. public PrecedingIterator (XPathSequence iter)
  880. : base (iter)
  881. {
  882. startPosition = Node.Clone ();
  883. }
  884. private PrecedingIterator (PrecedingIterator other, bool cloneFlag)
  885. : base (other, true)
  886. {
  887. startPosition = other.startPosition;
  888. started = other.started;
  889. finished = other.finished;
  890. }
  891. public override XPathSequence Clone ()
  892. {
  893. return new PrecedingIterator (this, true);
  894. }
  895. protected override bool MoveNextCore ()
  896. {
  897. if (finished)
  898. return false;
  899. if (!started) {
  900. started = true;
  901. Node.MoveToRoot ();
  902. }
  903. bool loop = true;
  904. while (loop) {
  905. while (!Node.MoveToFirstChild ()) {
  906. while (!Node.MoveToNext ()) {
  907. if (!Node.MoveToParent ()) { // Should not finish, at least before startPosition.
  908. finished = true;
  909. return false;
  910. }
  911. }
  912. break;
  913. }
  914. if (Node.IsDescendant (startPosition))
  915. continue;
  916. loop = false;
  917. break;
  918. }
  919. if (Node.ComparePosition (startPosition) != XmlNodeOrder.Before) {
  920. // Note that if _nav contains only 1 node, it won't be Same.
  921. finished = true;
  922. return false;
  923. }
  924. else
  925. return true;
  926. }
  927. public override bool ReverseAxis {
  928. get { return true; }
  929. }
  930. }
  931. internal class NamespaceIterator : NodeIterator
  932. {
  933. public NamespaceIterator (XPathSequence iter)
  934. : base (iter)
  935. {
  936. }
  937. private NamespaceIterator (NamespaceIterator other, bool cloneFlag)
  938. : base (other, true)
  939. {
  940. }
  941. public override XPathSequence Clone ()
  942. {
  943. return new NamespaceIterator (this, true);
  944. }
  945. protected override bool MoveNextCore ()
  946. {
  947. if (Position == 0) {
  948. if (Node.MoveToFirstNamespace ())
  949. return true;
  950. }
  951. else if (Node.MoveToNextNamespace ())
  952. return true;
  953. return false;
  954. }
  955. public override bool ReverseAxis { get { return true; } }
  956. }
  957. internal class AttributeIterator : NodeIterator
  958. {
  959. public AttributeIterator (XPathSequence iter)
  960. : base (iter)
  961. {
  962. }
  963. private AttributeIterator (AttributeIterator other, bool cloneFlag)
  964. : base (other, true)
  965. {
  966. }
  967. public override XPathSequence Clone ()
  968. {
  969. return new AttributeIterator (this, true);
  970. }
  971. protected override bool MoveNextCore ()
  972. {
  973. if (Position == 0) {
  974. if (Node.MoveToFirstAttribute ())
  975. return true;
  976. }
  977. else if (Node.MoveToNextAttribute ())
  978. return true;
  979. return false;
  980. }
  981. }
  982. // </copy>
  983. internal class ExprSequenceIterator : XPathSequence
  984. {
  985. XPathSequence contextSequence;
  986. XPathSequence iter;
  987. ExprSequence expr;
  988. int currentExprIndex;
  989. public ExprSequenceIterator (XPathSequence iter, ExprSequence expr)
  990. : base (iter.Context)
  991. {
  992. contextSequence = iter;
  993. this.expr = expr;
  994. }
  995. private ExprSequenceIterator (ExprSequenceIterator other)
  996. : base (other)
  997. {
  998. if (other.iter != null)
  999. iter = other.iter.Clone ();
  1000. expr = other.expr;
  1001. contextSequence = other.contextSequence;
  1002. currentExprIndex = other.currentExprIndex;
  1003. }
  1004. public override XPathSequence Clone ()
  1005. {
  1006. return new ExprSequenceIterator (this);
  1007. }
  1008. protected override bool MoveNextCore ()
  1009. {
  1010. if (iter != null && iter.MoveNext ())
  1011. return true;
  1012. while (currentExprIndex < expr.Count) {
  1013. iter = expr [currentExprIndex++].Evaluate (contextSequence);
  1014. if (iter.MoveNext ())
  1015. return true;
  1016. }
  1017. return false;
  1018. }
  1019. public override XPathItem CurrentCore {
  1020. get { return iter.Current; }
  1021. }
  1022. }
  1023. // FLWOR - Order By
  1024. internal class FLWORIterator : XPathSequence
  1025. {
  1026. XPathSequence contextSequence;
  1027. FLWORExpr expr;
  1028. ArrayList forStack = new ArrayList ();
  1029. IEnumerator en;
  1030. bool finished;
  1031. public FLWORIterator (XPathSequence iter, FLWORExpr expr)
  1032. : base (iter.Context)
  1033. {
  1034. this.contextSequence = iter;
  1035. this.expr = expr;
  1036. }
  1037. private FLWORIterator (FLWORIterator other)
  1038. : base (other)
  1039. {
  1040. contextSequence = other.contextSequence;
  1041. expr = other.expr;
  1042. forStack = other.forStack.Clone () as ArrayList;
  1043. if (en != null)
  1044. en = ((ICloneable) other.en).Clone () as IEnumerator;
  1045. finished = other.finished;
  1046. }
  1047. public override XPathSequence Clone ()
  1048. {
  1049. return new FLWORIterator (this);
  1050. }
  1051. #if false
  1052. protected override bool MoveNextCore ()
  1053. {
  1054. throw new NotImplementedException ();
  1055. }
  1056. #else
  1057. protected override bool MoveNextCore ()
  1058. {
  1059. if (en == null)
  1060. en = GetEnumerator ();
  1061. return en.MoveNext ();
  1062. }
  1063. public override IEnumerator GetEnumerator ()
  1064. {
  1065. IEnumerator forLetEnum = expr.ForLetClauses.GetEnumerator ();
  1066. // FIXME: this invokation seems to result in an Invalid IL error.
  1067. return EvaluateRemainingForLet (forLetEnum);
  1068. }
  1069. private IEnumerator EvaluateRemainingForLet (IEnumerator forLetEnum)
  1070. {
  1071. // Prepare iteration stack
  1072. if (forLetEnum.MoveNext ()) {
  1073. ForLetClause flc = (ForLetClause) forLetEnum.Current;
  1074. IEnumerator flsb = flc.GetEnumerator ();
  1075. IEnumerator items = EvaluateRemainingSingleItem (forLetEnum, flsb);
  1076. while (items.MoveNext ())
  1077. yield return items.Current;
  1078. yield break;
  1079. }
  1080. bool passedFilter = expr.WhereClause == null;
  1081. if (!passedFilter)
  1082. passedFilter = expr.WhereClause.EvaluateAsBoolean (contextSequence);
  1083. if (passedFilter) {
  1084. foreach (XPathItem item in expr.ReturnExpr.Evaluate (contextSequence))
  1085. yield return item;
  1086. }
  1087. }
  1088. private IEnumerator EvaluateRemainingSingleItem (IEnumerator forLetClauses, IEnumerator singleBodies)
  1089. {
  1090. if (singleBodies.MoveNext ()) {
  1091. ForLetSingleBody sb = singleBodies.Current as ForLetSingleBody;
  1092. ForSingleBody fsb = sb as ForSingleBody;
  1093. if (fsb != null) {
  1094. XPathSequence backup = contextSequence;
  1095. Context.ContextManager.PushCurrentSequence (sb.Expression.Evaluate (Context.CurrentSequence));
  1096. foreach (XPathItem forItem in Context.CurrentSequence) {
  1097. Context.PushVariable (fsb.PositionalVar, Context.CurrentSequence.Position);
  1098. Context.PushVariable (sb.VarName, forItem);
  1099. // recurse here (including following bindings)
  1100. IEnumerator items =
  1101. EvaluateRemainingSingleItem (forLetClauses, singleBodies);
  1102. while (items.MoveNext ())
  1103. yield return (XPathItem) items.Current;
  1104. Context.PopVariable ();
  1105. Context.PopVariable ();
  1106. }
  1107. Context.ContextManager.PopCurrentSequence ();
  1108. contextSequence = backup;
  1109. } else {
  1110. Context.PushVariable (sb.VarName, sb.Expression.Evaluate (contextSequence));
  1111. // recurse here (including following bindings)
  1112. IEnumerator items = EvaluateRemainingSingleItem (forLetClauses, singleBodies);
  1113. while (items.MoveNext ())
  1114. yield return (XPathItem) items.Current;
  1115. Context.PopVariable ();
  1116. }
  1117. } else {
  1118. // examine next binding
  1119. IEnumerator items = EvaluateRemainingForLet (forLetClauses);
  1120. while (items.MoveNext ())
  1121. yield return (XPathItem) items.Current;
  1122. }
  1123. }
  1124. #endif
  1125. public override XPathItem CurrentCore {
  1126. get { return (XPathItem) en.Current; }
  1127. }
  1128. }
  1129. internal class AtomizingIterator : XPathSequence
  1130. {
  1131. XPathSequence iter;
  1132. public AtomizingIterator (XPathSequence iter)
  1133. : base (iter.Context)
  1134. {
  1135. this.iter = iter;
  1136. }
  1137. private AtomizingIterator (AtomizingIterator other)
  1138. : base (other)
  1139. {
  1140. iter = other.iter.Clone ();
  1141. }
  1142. public override XPathSequence Clone ()
  1143. {
  1144. return new AtomizingIterator (this);
  1145. }
  1146. protected override bool MoveNextCore ()
  1147. {
  1148. return iter.MoveNext ();
  1149. }
  1150. public override XPathItem CurrentCore {
  1151. get {
  1152. XPathNavigator nav = iter.Current as XPathNavigator;
  1153. if (nav == null)
  1154. return (XPathAtomicValue) iter.Current;
  1155. if (nav.SchemaInfo != null)
  1156. return new XPathAtomicValue (
  1157. nav.TypedValue,
  1158. nav.SchemaInfo.SchemaType);
  1159. else
  1160. return new XPathAtomicValue (nav.Value, null);
  1161. }
  1162. }
  1163. }
  1164. internal class ConvertingIterator : XPathSequence
  1165. {
  1166. XPathSequence iter;
  1167. SequenceType type;
  1168. public ConvertingIterator (XPathSequence iter, SequenceType type)
  1169. : base (iter.Context)
  1170. {
  1171. this.iter = iter;
  1172. this.type = type;
  1173. }
  1174. private ConvertingIterator (ConvertingIterator other)
  1175. : base (other)
  1176. {
  1177. iter = other.iter.Clone ();
  1178. type = other.type;
  1179. }
  1180. public override XPathSequence Clone ()
  1181. {
  1182. return new ConvertingIterator (this);
  1183. }
  1184. protected override bool MoveNextCore ()
  1185. {
  1186. return iter.MoveNext ();
  1187. }
  1188. public override XPathItem CurrentCore {
  1189. get { return type.Convert (iter.Current); }
  1190. }
  1191. }
  1192. internal class TracingIterator : XPathSequence
  1193. {
  1194. XPathSequence iter;
  1195. string format;
  1196. public TracingIterator (XPathSequence iter, string format)
  1197. : base (iter.Context)
  1198. {
  1199. this.iter = iter;
  1200. this.format = format;
  1201. }
  1202. private TracingIterator (TracingIterator other)
  1203. : base (other)
  1204. {
  1205. iter = other.iter.Clone ();
  1206. format = other.format;
  1207. }
  1208. public override XPathSequence Clone ()
  1209. {
  1210. return new TracingIterator (this);
  1211. }
  1212. protected override bool MoveNextCore ()
  1213. {
  1214. if (!iter.MoveNext ())
  1215. return false;
  1216. // FIXME: use OnMessageEvent
  1217. string output = String.Format (format, iter.Current.TypedValue);
  1218. Context.StaticContext.OnMessageEvent (iter.Current, new TraceEventArgs (output));
  1219. return true;
  1220. }
  1221. public override XPathItem CurrentCore {
  1222. get { return iter.Current; }
  1223. }
  1224. internal class TraceEventArgs : QueryEventArgs
  1225. {
  1226. string message;
  1227. internal TraceEventArgs (string message)
  1228. {
  1229. this.message = message;
  1230. }
  1231. public override string Message {
  1232. get { return message; }
  1233. }
  1234. }
  1235. }
  1236. internal class ListIterator : XPathSequence
  1237. {
  1238. IList list;
  1239. public ListIterator (XPathSequence iter, IList list)
  1240. : base (iter.Context)
  1241. {
  1242. if (list is ICloneable)
  1243. this.list = list;
  1244. else
  1245. throw new InvalidOperationException (String.Format ("XQuery internal error: target list is not cloneable. List is {0}.", list != null ? list.GetType ().ToString () : "null argument"));
  1246. }
  1247. private ListIterator (ListIterator other)
  1248. : base (other)
  1249. {
  1250. this.list = (IList) ((ICloneable) other.list).Clone ();
  1251. }
  1252. public override XPathSequence Clone ()
  1253. {
  1254. return new ListIterator (this);
  1255. }
  1256. protected override bool MoveNextCore ()
  1257. {
  1258. return (Position < list.Count);
  1259. }
  1260. public override XPathItem CurrentCore {
  1261. get { return (XPathItem) list [Position - 1]; }
  1262. }
  1263. }
  1264. internal class EnumeratorIterator : XPathSequence
  1265. {
  1266. IEnumerator list;
  1267. public EnumeratorIterator (XQueryContext ctx, IEnumerable en)
  1268. : base (ctx)
  1269. {
  1270. list = en.GetEnumerator ();
  1271. if (list is ICloneable)
  1272. this.list = list;
  1273. else
  1274. throw new InvalidOperationException (String.Format ("XQuery internal error: target list's enumerator is not cloneable. List is {0}.", en != null ? en.GetType ().ToString () : "null argument"));
  1275. }
  1276. private EnumeratorIterator (EnumeratorIterator other)
  1277. : base (other)
  1278. {
  1279. this.list = (IEnumerator) ((ICloneable) other.list).Clone ();
  1280. }
  1281. public override XPathSequence Clone ()
  1282. {
  1283. return new EnumeratorIterator (this);
  1284. }
  1285. protected override bool MoveNextCore ()
  1286. {
  1287. return list.MoveNext ();
  1288. }
  1289. public override XPathItem CurrentCore {
  1290. get { return (XPathItem) list.Current; }
  1291. }
  1292. }
  1293. }
  1294. #endif