XPathSequence.cs 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501
  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 virtual int Position {
  76. get { return position; }
  77. }
  78. public virtual 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. bool emptyInput;
  522. public NodeIterator (XPathSequence iter)
  523. : base (iter.Context)
  524. {
  525. if (iter.Position == 0) {
  526. if (!iter.MoveNext ()) {
  527. emptyInput = true;
  528. return;
  529. }
  530. }
  531. XPathItem item = iter.Current;
  532. node = item as XPathNavigator;
  533. if (node == null)
  534. throw new XmlQueryException (String.Format ("Current item is expected to be a node, but it is {0} ({1}).", item.XmlType.QualifiedName, item.XmlType.TypeCode));
  535. node = node.Clone ();
  536. }
  537. internal NodeIterator (NodeIterator other, bool cloneFlag)
  538. : base (other)
  539. {
  540. if (other.emptyInput)
  541. emptyInput = true;
  542. else
  543. node = other.node.Clone ();
  544. }
  545. internal XPathNavigator Node {
  546. get { return node; }
  547. }
  548. public override bool MoveNext ()
  549. {
  550. if (emptyInput)
  551. return false;
  552. if (!base.MoveNext ())
  553. return false;
  554. current = null;
  555. return true;
  556. }
  557. public override XPathItem CurrentCore {
  558. get {
  559. if (current == null)
  560. current = node.Clone ();
  561. return current;
  562. }
  563. }
  564. public virtual bool ReverseAxis {
  565. get { return false; }
  566. }
  567. // public override bool RequireSorting {
  568. // get { return ReverseAxis; }
  569. // }
  570. }
  571. // <copy original='System.Xml.XPath/Iterator.cs'>
  572. internal class ParentIterator : NodeIterator
  573. {
  574. public ParentIterator (XPathSequence iter)
  575. : base (iter)
  576. {
  577. }
  578. private ParentIterator (ParentIterator other, bool cloneFlag)
  579. : base (other, true)
  580. {
  581. }
  582. public override XPathSequence Clone ()
  583. {
  584. return new ParentIterator (this, true);
  585. }
  586. protected override bool MoveNextCore ()
  587. {
  588. if (Position == 0 && Node.MoveToParent ())
  589. return true;
  590. return false;
  591. }
  592. public override bool ReverseAxis {
  593. get { return true; }
  594. }
  595. }
  596. internal class ChildIterator : NodeIterator
  597. {
  598. public ChildIterator (XPathSequence iter)
  599. : base (iter)
  600. {
  601. }
  602. private ChildIterator (ChildIterator other, bool cloneFlag)
  603. : base (other, true)
  604. {
  605. }
  606. public override XPathSequence Clone ()
  607. {
  608. return new ChildIterator (this, true);
  609. }
  610. protected override bool MoveNextCore ()
  611. {
  612. if (Position == 0)
  613. return Node.MoveToFirstChild ();
  614. else
  615. return Node.MoveToNext ();
  616. }
  617. }
  618. internal class FollowingSiblingIterator : NodeIterator
  619. {
  620. public FollowingSiblingIterator (XPathSequence iter)
  621. : base (iter)
  622. {
  623. }
  624. private FollowingSiblingIterator (FollowingSiblingIterator other, bool cloneFlag)
  625. : base (other, true)
  626. {
  627. }
  628. public override XPathSequence Clone ()
  629. {
  630. return new FollowingSiblingIterator (this, true);
  631. }
  632. protected override bool MoveNextCore ()
  633. {
  634. return Node.MoveToNext ();
  635. }
  636. }
  637. internal class PrecedingSiblingIterator : NodeIterator
  638. {
  639. bool finished;
  640. bool started;
  641. XPathNavigator startPosition;
  642. public PrecedingSiblingIterator (XPathSequence iter)
  643. : base (iter)
  644. {
  645. startPosition = Node.Clone ();
  646. }
  647. private PrecedingSiblingIterator (PrecedingSiblingIterator other, bool cloneFlag)
  648. : base (other, true)
  649. {
  650. startPosition = other.startPosition;
  651. started = other.started;
  652. finished = other.finished;
  653. }
  654. public override XPathSequence Clone ()
  655. {
  656. return new PrecedingSiblingIterator (this, true);
  657. }
  658. protected override bool MoveNextCore ()
  659. {
  660. if (finished)
  661. return false;
  662. if (!started) {
  663. started = true;
  664. Node.MoveToFirst ();
  665. } else {
  666. Node.MoveToNext ();
  667. }
  668. if (Node.ComparePosition (startPosition) == XmlNodeOrder.Same) {
  669. finished = true;
  670. return false;
  671. }
  672. else
  673. return true;
  674. }
  675. public override bool ReverseAxis {
  676. get { return true; }
  677. }
  678. }
  679. internal class AncestorIterator : NodeIterator
  680. {
  681. bool finished;
  682. ArrayList nodes = new ArrayList ();
  683. public AncestorIterator (XPathSequence iter)
  684. : base (iter)
  685. {
  686. }
  687. private AncestorIterator (AncestorIterator other, bool cloneFlag)
  688. : base (other, true)
  689. {
  690. finished = other.finished;
  691. nodes = other.nodes;
  692. }
  693. public override XPathSequence Clone ()
  694. {
  695. return new AncestorIterator (this, true);
  696. }
  697. protected override bool MoveNextCore ()
  698. {
  699. if (finished)
  700. return false;
  701. if (nodes != null) {
  702. nodes = new ArrayList ();
  703. while (Node.MoveToParent () && Node.NodeType != XPathNodeType.Root)
  704. nodes.Add (Node.Clone ());
  705. nodes.Reverse ();
  706. }
  707. if (nodes.Count >= Position)
  708. return false;
  709. Node.MoveTo (nodes [Position] as XPathNavigator);
  710. return true;
  711. }
  712. public override bool ReverseAxis {
  713. get { return true; }
  714. }
  715. public override int Count {
  716. get {
  717. if (Position == 0)
  718. return base.Count;
  719. return nodes.Count;
  720. }
  721. }
  722. }
  723. internal class AncestorOrSelfIterator : NodeIterator
  724. {
  725. bool finished;
  726. ArrayList nodes = new ArrayList ();
  727. public AncestorOrSelfIterator (XPathSequence iter)
  728. : base (iter)
  729. {
  730. }
  731. private AncestorOrSelfIterator (AncestorOrSelfIterator other, bool cloneFlag)
  732. : base (other, true)
  733. {
  734. finished = other.finished;
  735. nodes = other.nodes;
  736. }
  737. public override XPathSequence Clone ()
  738. {
  739. return new AncestorOrSelfIterator (this, true);
  740. }
  741. protected override bool MoveNextCore ()
  742. {
  743. if (finished)
  744. return false;
  745. if (nodes != null) {
  746. nodes = new ArrayList ();
  747. do {
  748. nodes.Add (Node.Clone ());
  749. } while (Node.MoveToParent () && Node.NodeType != XPathNodeType.Root);
  750. nodes.Reverse ();
  751. }
  752. if (nodes.Count >= Position)
  753. return false;
  754. Node.MoveTo (nodes [Position] as XPathNavigator);
  755. return true;
  756. }
  757. public override bool ReverseAxis {
  758. get { return true; }
  759. }
  760. public override int Count {
  761. get {
  762. if (Position == 0)
  763. return base.Count;
  764. return nodes.Count;
  765. }
  766. }
  767. }
  768. internal class DescendantIterator : NodeIterator
  769. {
  770. private int depth;
  771. private bool finished;
  772. public DescendantIterator (XPathSequence iter)
  773. : base (iter)
  774. {
  775. }
  776. private DescendantIterator (DescendantIterator other, bool cloneFlag)
  777. : base (other, true)
  778. {
  779. finished = other.finished;
  780. depth = other.depth;
  781. }
  782. public override XPathSequence Clone ()
  783. {
  784. return new DescendantIterator (this, true);
  785. }
  786. protected override bool MoveNextCore ()
  787. {
  788. if (finished)
  789. return false;
  790. if (Node.MoveToFirstChild ()) {
  791. depth ++;
  792. return true;
  793. }
  794. while (depth != 0) {
  795. if (Node.MoveToNext ())
  796. return true;
  797. if (!Node.MoveToParent ()) // should NEVER fail!
  798. throw new XmlQueryException ("There seems some bugs on the XPathNavigator implementation class.");
  799. depth --;
  800. }
  801. finished = true;
  802. return false;
  803. }
  804. }
  805. internal class DescendantOrSelfIterator : NodeIterator
  806. {
  807. protected int depth;
  808. private bool finished;
  809. public DescendantOrSelfIterator (XPathSequence iter)
  810. : base (iter)
  811. {
  812. }
  813. protected DescendantOrSelfIterator (DescendantOrSelfIterator other, bool cloneFlag)
  814. : base (other, true)
  815. {
  816. depth = other.depth;
  817. finished = other.finished;
  818. }
  819. public override XPathSequence Clone ()
  820. {
  821. return new DescendantOrSelfIterator (this, true);
  822. }
  823. protected override bool MoveNextCore ()
  824. {
  825. if (finished)
  826. return false;
  827. if (Position == 0)
  828. return true; // Self
  829. if (Node.MoveToFirstChild ()) {
  830. depth ++;
  831. return true;
  832. }
  833. while (depth != 0) {
  834. if (Node.MoveToNext ())
  835. return true;
  836. if (!Node.MoveToParent ()) // should NEVER fail!
  837. throw new XmlQueryException ("There seems some bugs on the XPathNavigator implementation class.");
  838. depth --;
  839. }
  840. finished = true;
  841. return false;
  842. }
  843. }
  844. internal class FollowingIterator : NodeIterator
  845. {
  846. private bool finished;
  847. public FollowingIterator (XPathSequence iter)
  848. : base (iter)
  849. {
  850. }
  851. protected FollowingIterator (FollowingIterator other, bool cloneFlag)
  852. : base (other, true)
  853. {
  854. finished = other.finished;
  855. }
  856. public override XPathSequence Clone ()
  857. {
  858. return new FollowingIterator (this, true);
  859. }
  860. protected override bool MoveNextCore ()
  861. {
  862. if (finished)
  863. return false;
  864. if (Position == 0) {
  865. // At first, it should not iterate children.
  866. if (Node.MoveToNext ())
  867. return true;
  868. else {
  869. while (Node.MoveToParent ())
  870. if (Node.MoveToNext ())
  871. return true;
  872. }
  873. } else {
  874. if (Node.MoveToFirstChild ())
  875. return true;
  876. do {
  877. if (Node.MoveToNext ())
  878. return true;
  879. } while (Node.MoveToParent ());
  880. }
  881. finished = true;
  882. return false;
  883. }
  884. }
  885. internal class PrecedingIterator : NodeIterator
  886. {
  887. bool finished;
  888. bool started;
  889. XPathNavigator startPosition;
  890. public PrecedingIterator (XPathSequence iter)
  891. : base (iter)
  892. {
  893. startPosition = Node.Clone ();
  894. }
  895. private PrecedingIterator (PrecedingIterator other, bool cloneFlag)
  896. : base (other, true)
  897. {
  898. startPosition = other.startPosition;
  899. started = other.started;
  900. finished = other.finished;
  901. }
  902. public override XPathSequence Clone ()
  903. {
  904. return new PrecedingIterator (this, true);
  905. }
  906. protected override bool MoveNextCore ()
  907. {
  908. if (finished)
  909. return false;
  910. if (!started) {
  911. started = true;
  912. Node.MoveToRoot ();
  913. }
  914. bool loop = true;
  915. while (loop) {
  916. while (!Node.MoveToFirstChild ()) {
  917. while (!Node.MoveToNext ()) {
  918. if (!Node.MoveToParent ()) { // Should not finish, at least before startPosition.
  919. finished = true;
  920. return false;
  921. }
  922. }
  923. break;
  924. }
  925. if (Node.IsDescendant (startPosition))
  926. continue;
  927. loop = false;
  928. break;
  929. }
  930. if (Node.ComparePosition (startPosition) != XmlNodeOrder.Before) {
  931. // Note that if _nav contains only 1 node, it won't be Same.
  932. finished = true;
  933. return false;
  934. }
  935. else
  936. return true;
  937. }
  938. public override bool ReverseAxis {
  939. get { return true; }
  940. }
  941. }
  942. internal class NamespaceIterator : NodeIterator
  943. {
  944. public NamespaceIterator (XPathSequence iter)
  945. : base (iter)
  946. {
  947. }
  948. private NamespaceIterator (NamespaceIterator other, bool cloneFlag)
  949. : base (other, true)
  950. {
  951. }
  952. public override XPathSequence Clone ()
  953. {
  954. return new NamespaceIterator (this, true);
  955. }
  956. protected override bool MoveNextCore ()
  957. {
  958. if (Position == 0) {
  959. if (Node.MoveToFirstNamespace ())
  960. return true;
  961. }
  962. else if (Node.MoveToNextNamespace ())
  963. return true;
  964. return false;
  965. }
  966. public override bool ReverseAxis { get { return true; } }
  967. }
  968. internal class AttributeIterator : NodeIterator
  969. {
  970. public AttributeIterator (XPathSequence iter)
  971. : base (iter)
  972. {
  973. }
  974. private AttributeIterator (AttributeIterator other, bool cloneFlag)
  975. : base (other, true)
  976. {
  977. }
  978. public override XPathSequence Clone ()
  979. {
  980. return new AttributeIterator (this, true);
  981. }
  982. protected override bool MoveNextCore ()
  983. {
  984. if (Position == 0) {
  985. if (Node.MoveToFirstAttribute ())
  986. return true;
  987. }
  988. else if (Node.MoveToNextAttribute ())
  989. return true;
  990. return false;
  991. }
  992. }
  993. // </copy>
  994. internal class ExprSequenceIterator : XPathSequence
  995. {
  996. XPathSequence contextSequence;
  997. XPathSequence iter;
  998. ExprSequence expr;
  999. int currentExprIndex;
  1000. public ExprSequenceIterator (XPathSequence iter, ExprSequence expr)
  1001. : base (iter.Context)
  1002. {
  1003. contextSequence = iter;
  1004. this.expr = expr;
  1005. }
  1006. private ExprSequenceIterator (ExprSequenceIterator other)
  1007. : base (other)
  1008. {
  1009. if (other.iter != null)
  1010. iter = other.iter.Clone ();
  1011. expr = other.expr;
  1012. contextSequence = other.contextSequence;
  1013. currentExprIndex = other.currentExprIndex;
  1014. }
  1015. public override XPathSequence Clone ()
  1016. {
  1017. return new ExprSequenceIterator (this);
  1018. }
  1019. protected override bool MoveNextCore ()
  1020. {
  1021. if (iter != null && iter.MoveNext ())
  1022. return true;
  1023. while (currentExprIndex < expr.Count) {
  1024. iter = expr [currentExprIndex++].Evaluate (contextSequence);
  1025. if (iter.MoveNext ())
  1026. return true;
  1027. }
  1028. return false;
  1029. }
  1030. public override XPathItem CurrentCore {
  1031. get { return iter.Current; }
  1032. }
  1033. }
  1034. // FLWOR - Order By
  1035. internal class FLWORIterator : XPathSequence
  1036. {
  1037. XPathSequence contextSequence;
  1038. FLWORExpr expr;
  1039. ArrayList forStack = new ArrayList ();
  1040. IEnumerator en;
  1041. bool finished;
  1042. public FLWORIterator (XPathSequence iter, FLWORExpr expr)
  1043. : base (iter.Context)
  1044. {
  1045. this.contextSequence = iter;
  1046. this.expr = expr;
  1047. }
  1048. private FLWORIterator (FLWORIterator other)
  1049. : base (other)
  1050. {
  1051. contextSequence = other.contextSequence;
  1052. expr = other.expr;
  1053. forStack = other.forStack.Clone () as ArrayList;
  1054. if (en != null)
  1055. en = ((ICloneable) other.en).Clone () as IEnumerator;
  1056. finished = other.finished;
  1057. }
  1058. public override XPathSequence Clone ()
  1059. {
  1060. return new FLWORIterator (this);
  1061. }
  1062. #if false
  1063. protected override bool MoveNextCore ()
  1064. {
  1065. throw new NotImplementedException ();
  1066. }
  1067. #else
  1068. protected override bool MoveNextCore ()
  1069. {
  1070. if (en == null)
  1071. en = GetEnumerator ();
  1072. return en.MoveNext ();
  1073. }
  1074. public override IEnumerator GetEnumerator ()
  1075. {
  1076. IEnumerator forLetEnum = expr.ForLetClauses.GetEnumerator ();
  1077. // FIXME: this invokation seems to result in an Invalid IL error.
  1078. return EvaluateRemainingForLet (forLetEnum);
  1079. }
  1080. private IEnumerator EvaluateRemainingForLet (IEnumerator forLetEnum)
  1081. {
  1082. // Prepare iteration stack
  1083. if (forLetEnum.MoveNext ()) {
  1084. ForLetClause flc = (ForLetClause) forLetEnum.Current;
  1085. IEnumerator flsb = flc.GetEnumerator ();
  1086. IEnumerator items = EvaluateRemainingSingleItem (forLetEnum, flsb);
  1087. while (items.MoveNext ())
  1088. yield return items.Current;
  1089. yield break;
  1090. }
  1091. bool passedFilter = expr.WhereClause == null;
  1092. if (!passedFilter)
  1093. passedFilter = expr.WhereClause.EvaluateAsBoolean (contextSequence);
  1094. if (passedFilter) {
  1095. foreach (XPathItem item in expr.ReturnExpr.Evaluate (contextSequence))
  1096. yield return item;
  1097. }
  1098. }
  1099. private IEnumerator EvaluateRemainingSingleItem (IEnumerator forLetClauses, IEnumerator singleBodies)
  1100. {
  1101. if (singleBodies.MoveNext ()) {
  1102. ForLetSingleBody sb = singleBodies.Current as ForLetSingleBody;
  1103. ForSingleBody fsb = sb as ForSingleBody;
  1104. if (fsb != null) {
  1105. XPathSequence backup = contextSequence;
  1106. Context.ContextManager.PushCurrentSequence (sb.Expression.Evaluate (Context.CurrentSequence));
  1107. foreach (XPathItem forItem in Context.CurrentSequence) {
  1108. Context.PushVariable (fsb.PositionalVar, Context.CurrentSequence.Position);
  1109. Context.PushVariable (sb.VarName, forItem);
  1110. // recurse here (including following bindings)
  1111. IEnumerator items =
  1112. EvaluateRemainingSingleItem (forLetClauses, singleBodies);
  1113. while (items.MoveNext ())
  1114. yield return (XPathItem) items.Current;
  1115. Context.PopVariable ();
  1116. Context.PopVariable ();
  1117. }
  1118. Context.ContextManager.PopCurrentSequence ();
  1119. contextSequence = backup;
  1120. } else {
  1121. Context.PushVariable (sb.VarName, sb.Expression.Evaluate (contextSequence));
  1122. // recurse here (including following bindings)
  1123. IEnumerator items = EvaluateRemainingSingleItem (forLetClauses, singleBodies);
  1124. while (items.MoveNext ())
  1125. yield return (XPathItem) items.Current;
  1126. Context.PopVariable ();
  1127. }
  1128. } else {
  1129. // examine next binding
  1130. IEnumerator items = EvaluateRemainingForLet (forLetClauses);
  1131. while (items.MoveNext ())
  1132. yield return (XPathItem) items.Current;
  1133. }
  1134. }
  1135. #endif
  1136. public override XPathItem CurrentCore {
  1137. get { return (XPathItem) en.Current; }
  1138. }
  1139. }
  1140. internal class AtomizingIterator : XPathSequence
  1141. {
  1142. XPathSequence iter;
  1143. public AtomizingIterator (XPathSequence iter)
  1144. : base (iter.Context)
  1145. {
  1146. this.iter = iter;
  1147. }
  1148. private AtomizingIterator (AtomizingIterator other)
  1149. : base (other)
  1150. {
  1151. iter = other.iter.Clone ();
  1152. }
  1153. public override XPathSequence Clone ()
  1154. {
  1155. return new AtomizingIterator (this);
  1156. }
  1157. protected override bool MoveNextCore ()
  1158. {
  1159. return iter.MoveNext ();
  1160. }
  1161. public override XPathItem CurrentCore {
  1162. get {
  1163. XPathNavigator nav = iter.Current as XPathNavigator;
  1164. if (nav == null)
  1165. return (XPathAtomicValue) iter.Current;
  1166. if (nav.SchemaInfo != null)
  1167. return new XPathAtomicValue (
  1168. nav.TypedValue,
  1169. nav.SchemaInfo.SchemaType);
  1170. else
  1171. return new XPathAtomicValue (nav.Value, null);
  1172. }
  1173. }
  1174. }
  1175. internal class ConvertingIterator : XPathSequence
  1176. {
  1177. XPathSequence iter;
  1178. SequenceType type;
  1179. public ConvertingIterator (XPathSequence iter, SequenceType type)
  1180. : base (iter.Context)
  1181. {
  1182. this.iter = iter;
  1183. this.type = type;
  1184. }
  1185. private ConvertingIterator (ConvertingIterator other)
  1186. : base (other)
  1187. {
  1188. iter = other.iter.Clone ();
  1189. type = other.type;
  1190. }
  1191. public override XPathSequence Clone ()
  1192. {
  1193. return new ConvertingIterator (this);
  1194. }
  1195. protected override bool MoveNextCore ()
  1196. {
  1197. return iter.MoveNext ();
  1198. }
  1199. public override XPathItem CurrentCore {
  1200. get { return type.Convert (iter.Current); }
  1201. }
  1202. }
  1203. internal class TracingIterator : XPathSequence
  1204. {
  1205. XPathSequence iter;
  1206. string format;
  1207. public TracingIterator (XPathSequence iter, string format)
  1208. : base (iter.Context)
  1209. {
  1210. this.iter = iter;
  1211. this.format = format;
  1212. }
  1213. private TracingIterator (TracingIterator other)
  1214. : base (other)
  1215. {
  1216. iter = other.iter.Clone ();
  1217. format = other.format;
  1218. }
  1219. public override XPathSequence Clone ()
  1220. {
  1221. return new TracingIterator (this);
  1222. }
  1223. protected override bool MoveNextCore ()
  1224. {
  1225. if (!iter.MoveNext ())
  1226. return false;
  1227. // FIXME: use OnMessageEvent
  1228. string output = String.Format (format, iter.Current.TypedValue);
  1229. Context.StaticContext.OnMessageEvent (iter.Current, new TraceEventArgs (output));
  1230. return true;
  1231. }
  1232. public override XPathItem CurrentCore {
  1233. get { return iter.Current; }
  1234. }
  1235. internal class TraceEventArgs : QueryEventArgs
  1236. {
  1237. string message;
  1238. internal TraceEventArgs (string message)
  1239. {
  1240. this.message = message;
  1241. }
  1242. public override string Message {
  1243. get { return message; }
  1244. }
  1245. }
  1246. }
  1247. internal class ListIterator : XPathSequence
  1248. {
  1249. IList list;
  1250. public ListIterator (XPathSequence iter, IList list)
  1251. : base (iter.Context)
  1252. {
  1253. if (list is ICloneable)
  1254. this.list = list;
  1255. else
  1256. throw new InvalidOperationException (String.Format ("XQuery internal error: target list is not cloneable. List is {0}.", list != null ? list.GetType ().ToString () : "null argument"));
  1257. }
  1258. private ListIterator (ListIterator other)
  1259. : base (other)
  1260. {
  1261. this.list = (IList) ((ICloneable) other.list).Clone ();
  1262. }
  1263. public override XPathSequence Clone ()
  1264. {
  1265. return new ListIterator (this);
  1266. }
  1267. protected override bool MoveNextCore ()
  1268. {
  1269. return (Position < list.Count);
  1270. }
  1271. public override XPathItem CurrentCore {
  1272. get { return (XPathItem) list [Position - 1]; }
  1273. }
  1274. }
  1275. internal class EnumeratorIterator : XPathSequence
  1276. {
  1277. IEnumerator list;
  1278. public EnumeratorIterator (XQueryContext ctx, IEnumerable en)
  1279. : base (ctx)
  1280. {
  1281. list = en.GetEnumerator ();
  1282. if (list is ICloneable)
  1283. this.list = list;
  1284. else
  1285. 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"));
  1286. }
  1287. private EnumeratorIterator (EnumeratorIterator other)
  1288. : base (other)
  1289. {
  1290. this.list = (IEnumerator) ((ICloneable) other.list).Clone ();
  1291. }
  1292. public override XPathSequence Clone ()
  1293. {
  1294. return new EnumeratorIterator (this);
  1295. }
  1296. protected override bool MoveNextCore ()
  1297. {
  1298. return list.MoveNext ();
  1299. }
  1300. public override XPathItem CurrentCore {
  1301. get { return (XPathItem) list.Current; }
  1302. }
  1303. }
  1304. }
  1305. #endif