XPathSequence.cs 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780
  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.Globalization;
  33. using System.Xml;
  34. using System.Xml.Schema;
  35. using System.Xml.Query;
  36. using System.Xml.XPath;
  37. namespace Mono.Xml.XPath2
  38. {
  39. public abstract class XPathSequence : IEnumerable, ICloneable
  40. {
  41. XQueryContext ctx;
  42. int countCache = -1;
  43. int position = 0;
  44. internal XPathSequence (XQueryContext ctx)
  45. {
  46. this.ctx = ctx;
  47. }
  48. internal XPathSequence (XPathSequence original)
  49. {
  50. ctx = original.ctx;
  51. position = original.position;
  52. }
  53. internal XQueryContext Context {
  54. // get { return ctx; }
  55. get { return ctx.ContextManager.CurrentContext; }
  56. }
  57. public virtual int Count {
  58. get {
  59. if (countCache >= 0)
  60. return countCache;
  61. XPathSequence clone = Clone ();
  62. while (clone.MoveNext ())
  63. ;
  64. countCache = clone.Position;
  65. return countCache;
  66. }
  67. }
  68. public XPathItem Current {
  69. get {
  70. if (Position == 0)
  71. throw new InvalidOperationException ("XQuery internal error (should not happen)");
  72. return CurrentCore;
  73. }
  74. }
  75. public abstract XPathItem CurrentCore { get; }
  76. // Returns 0 if not started, otherwise returns XPath positional integer.
  77. public virtual int Position {
  78. get { return position; }
  79. }
  80. public virtual bool MoveNext ()
  81. {
  82. if (!MoveNextCore ())
  83. return false;
  84. position++;
  85. return true;
  86. }
  87. protected abstract bool MoveNextCore ();
  88. public abstract XPathSequence Clone ();
  89. object ICloneable.Clone ()
  90. {
  91. return this.Clone ();
  92. }
  93. public virtual IEnumerator GetEnumerator ()
  94. {
  95. while (MoveNext ())
  96. yield return CurrentCore;
  97. }
  98. }
  99. // empty iterator (still required since it contains XQueryContext)
  100. class XPathEmptySequence : XPathSequence
  101. {
  102. internal XPathEmptySequence (XQueryContext ctx)
  103. : base (ctx)
  104. {
  105. }
  106. public override int Count {
  107. get { return 0; }
  108. }
  109. protected override bool MoveNextCore ()
  110. {
  111. return false;
  112. }
  113. public override XPathItem CurrentCore {
  114. get { throw new InvalidOperationException ("Should not happen. In XPathEmptySequence.Current."); }
  115. }
  116. // Don't return clone. It's waste of resource.
  117. public override XPathSequence Clone ()
  118. {
  119. return this;
  120. }
  121. }
  122. // single item iterator
  123. internal class SingleItemIterator : XPathSequence
  124. {
  125. XPathItem item;
  126. XPathItem current;
  127. // for XQuery execution start point
  128. internal SingleItemIterator (XPathItem item, XQueryContext ctx)
  129. : base (ctx)
  130. {
  131. this.item = item;
  132. }
  133. private SingleItemIterator (SingleItemIterator other)
  134. : base (other)
  135. {
  136. this.item = other.item;
  137. this.current = other.current;
  138. }
  139. public override XPathSequence Clone ()
  140. {
  141. return new SingleItemIterator (this);
  142. }
  143. protected override bool MoveNextCore ()
  144. {
  145. if (current == null) {
  146. current = item;
  147. return true;
  148. }
  149. return false;
  150. }
  151. public override XPathItem CurrentCore {
  152. get {
  153. return current;
  154. }
  155. }
  156. }
  157. // RangeExpr iterator
  158. internal class IntegerRangeIterator : XPathSequence
  159. {
  160. static XmlSchemaSimpleType intType = XmlSchemaType.GetBuiltInSimpleType (new XmlQualifiedName ("int", XmlSchema.Namespace));
  161. int start;
  162. int end;
  163. int next;
  164. XPathItem current;
  165. public IntegerRangeIterator (XQueryContext ctx, int start, int end)
  166. : base (ctx)
  167. {
  168. this.start = start;
  169. this.end = end;
  170. }
  171. private IntegerRangeIterator (IntegerRangeIterator other)
  172. : base (other)
  173. {
  174. this.start = other.start;
  175. this.end = other.end;
  176. this.next = other.next;
  177. this.current = other.current;
  178. }
  179. public override XPathSequence Clone ()
  180. {
  181. return new IntegerRangeIterator (this);
  182. }
  183. protected override bool MoveNextCore ()
  184. {
  185. if (current == null)
  186. next = start;
  187. if (next > end)
  188. return false;
  189. current = new XPathAtomicValue (next++, intType);
  190. return true;
  191. }
  192. public override XPathItem CurrentCore {
  193. get {
  194. return current;
  195. }
  196. }
  197. }
  198. // Slash iterator
  199. // <copy original='System.Xml.XPath/Iterator.cs,
  200. // System.Xml.XPath/XPathComparer.cs'>
  201. internal class PathStepIterator : XPathSequence
  202. {
  203. XPathSequence left;
  204. XPathSequence right;
  205. PathStepExpr step;
  206. ArrayList nodeStore;
  207. SortedList storedIterators;
  208. bool finished;
  209. XPathSequence nextRight;
  210. public PathStepIterator (XPathSequence iter, PathStepExpr source)
  211. : base (iter.Context)
  212. {
  213. left = iter;
  214. step = source;
  215. }
  216. private PathStepIterator (PathStepIterator other)
  217. : base (other)
  218. {
  219. left = other.left.Clone ();
  220. step = other.step;
  221. if (other.right != null)
  222. right = other.right.Clone ();
  223. if (other.nodeStore != null)
  224. nodeStore = (ArrayList) other.nodeStore.Clone ();
  225. if (other.storedIterators != null)
  226. storedIterators = (SortedList) other.storedIterators.Clone ();
  227. if (other.nextRight != null)
  228. nextRight = other.nextRight.Clone ();
  229. }
  230. public override XPathSequence Clone ()
  231. {
  232. return new PathStepIterator (this);
  233. }
  234. protected override bool MoveNextCore ()
  235. {
  236. if (finished)
  237. return false;
  238. if (step.RequireSorting) {
  239. // Mainly '//' ('/descendant-or-self::node()/')
  240. if (nodeStore == null) {
  241. CollectResults ();
  242. if (nodeStore.Count == 0) {
  243. finished = true;
  244. return false;
  245. } else
  246. // Initially it must not go to
  247. // the while loop below
  248. // (.Position -1 is -1).
  249. return true;
  250. }
  251. if (nodeStore.Count == Position) {
  252. finished = true;
  253. return false;
  254. }
  255. while (nodeStore.Count > Position) {
  256. if (((XPathNavigator) nodeStore [Position]).ComparePosition (
  257. (XPathNavigator) nodeStore [Position - 1]) == XmlNodeOrder.Same)
  258. nodeStore.RemoveAt (Position);
  259. else
  260. break;
  261. }
  262. return true;
  263. } else { // Sorting not required
  264. if (right == null) { // First time
  265. if (!left.MoveNext ())
  266. return false;
  267. right = step.Next.Evaluate (left);
  268. storedIterators = new SortedList (XPathSequenceComparer.Instance);
  269. }
  270. while (true) {
  271. while (!right.MoveNext ()) {
  272. if (storedIterators.Count > 0) {
  273. int last = storedIterators.Count - 1;
  274. XPathSequence tmpIter = (XPathSequence) storedIterators.GetByIndex (last);
  275. storedIterators.RemoveAt (last);
  276. switch (((XPathNavigator) tmpIter.Current).ComparePosition ((XPathNavigator) right.Current)) {
  277. case XmlNodeOrder.Same:
  278. case XmlNodeOrder.Before:
  279. right = tmpIter;
  280. continue;
  281. default:
  282. right = tmpIter;
  283. break;
  284. }
  285. break;
  286. } else if (nextRight != null) {
  287. right = nextRight;
  288. nextRight = null;
  289. break;
  290. } else if (!left.MoveNext ()) {
  291. finished = true;
  292. return false;
  293. }
  294. else
  295. right = step.Next.Evaluate (left);
  296. }
  297. bool loop = true;
  298. while (loop) {
  299. loop = false;
  300. if (nextRight == null) {
  301. bool noMoreNext = false;
  302. while (nextRight == null || !nextRight.MoveNext ()) {
  303. if(left.MoveNext ())
  304. nextRight = step.Next.Evaluate (left);
  305. else {
  306. noMoreNext = true;
  307. break;
  308. }
  309. }
  310. if (noMoreNext)
  311. nextRight = null; // FIXME: More efficient code. Maybe making noMoreNext class scope would be better.
  312. }
  313. if (nextRight != null) {
  314. switch (((XPathNavigator) right.Current).ComparePosition ((XPathNavigator) nextRight.Current)) {
  315. case XmlNodeOrder.After:
  316. storedIterators.Add (storedIterators.Count, right);
  317. right = nextRight;
  318. nextRight = null;
  319. loop = true;
  320. break;
  321. case XmlNodeOrder.Same:
  322. if (!nextRight.MoveNext ())
  323. nextRight = null;
  324. else {
  325. int last = storedIterators.Count;
  326. if (last > 0) {
  327. storedIterators.Add (last, nextRight);
  328. nextRight = (XPathSequence) storedIterators.GetByIndex (last);
  329. storedIterators.RemoveAt (last);
  330. }
  331. }
  332. loop = true;
  333. break;
  334. }
  335. }
  336. }
  337. return true;
  338. }
  339. }
  340. }
  341. private void CollectResults ()
  342. {
  343. if (nodeStore != null)
  344. return;
  345. nodeStore = new ArrayList ();
  346. while (true) {
  347. while (right == null || !right.MoveNext ()) {
  348. if (!left.MoveNext ()) {
  349. nodeStore.Sort (XPathNavigatorComparer2.Instance);
  350. return;
  351. }
  352. right = step.Next.Evaluate (left);
  353. }
  354. XPathNavigator nav = (XPathNavigator) right.Current;
  355. nodeStore.Add (nav);
  356. }
  357. }
  358. public override XPathItem CurrentCore {
  359. get {
  360. if (Position <= 0) return null;
  361. if (step.RequireSorting) {
  362. return (XPathNavigator) nodeStore [Position - 1];
  363. } else {
  364. return right.Current;
  365. }
  366. }
  367. }
  368. public override int Count {
  369. get {
  370. if (nodeStore == null)
  371. return base.Count;
  372. else
  373. return nodeStore.Count;
  374. }
  375. }
  376. internal class XPathSequenceComparer : IComparer
  377. {
  378. public static XPathSequenceComparer Instance = new XPathSequenceComparer ();
  379. private XPathSequenceComparer ()
  380. {
  381. }
  382. public int Compare (object o1, object o2)
  383. {
  384. XPathSequence nav1 = o1 as XPathSequence;
  385. XPathSequence nav2 = o2 as XPathSequence;
  386. if (nav1 == null)
  387. return -1;
  388. if (nav2 == null)
  389. return 1;
  390. switch (((XPathNavigator) nav1.Current).ComparePosition ((XPathNavigator) nav2.Current)) {
  391. case XmlNodeOrder.Same:
  392. return 0;
  393. case XmlNodeOrder.After:
  394. return -1;
  395. default:
  396. return 1;
  397. }
  398. }
  399. }
  400. internal class XPathNavigatorComparer2 : IComparer
  401. {
  402. public static XPathNavigatorComparer2 Instance = new XPathNavigatorComparer2 ();
  403. private XPathNavigatorComparer2 ()
  404. {
  405. }
  406. public int Compare (object o1, object o2)
  407. {
  408. XPathNavigator nav1 = o1 as XPathNavigator;
  409. XPathNavigator nav2 = o2 as XPathNavigator;
  410. if (nav1 == null)
  411. return -1;
  412. if (nav2 == null)
  413. return 1;
  414. switch (nav1.ComparePosition (nav2)) {
  415. case XmlNodeOrder.Same:
  416. return 0;
  417. case XmlNodeOrder.After:
  418. return 1;
  419. default:
  420. return -1;
  421. }
  422. }
  423. }
  424. }
  425. // </copy>
  426. // Filter step iterator
  427. internal class FilteredIterator : XPathSequence
  428. {
  429. XPathSequence left;
  430. ExprSequence filter;
  431. public FilteredIterator (XPathSequence iter, FilterStepExpr source)
  432. : base (iter.Context)
  433. {
  434. left = source.Expr.Evaluate (iter);
  435. filter = source.Predicate;
  436. }
  437. private FilteredIterator (FilteredIterator other)
  438. : base (other)
  439. {
  440. left = other.left.Clone ();
  441. filter = other.filter;
  442. }
  443. public override XPathSequence Clone ()
  444. {
  445. return new FilteredIterator (this);
  446. }
  447. protected override bool MoveNextCore ()
  448. {
  449. // FIXME: as for numeric predicates, it is MUCH faster
  450. // when it skips apparent non-candidates, with possible
  451. // method implementation "XPathSequence.SkipTo (int)".
  452. // When it comes true, iteration won't be done first.
  453. while (left.MoveNext ()) {
  454. bool doesntPass = true;
  455. // Treat as OK if any of filter expr passed.
  456. // FIXME: handle numeric predicate.
  457. foreach (ExprSingle single in filter) {
  458. XPathAtomicValue av = single.EvaluateAsAtomic (left);
  459. if (av == null)
  460. continue;
  461. if (SequenceType.IsNumeric (av.XmlType.TypeCode)) {
  462. // numeric filter
  463. if (av.ValueAsInt32 == left.Position) {
  464. doesntPass = false;
  465. break;
  466. }
  467. }
  468. else if (single.EvaluateAsBoolean (left)) {
  469. doesntPass = false;
  470. break;
  471. }
  472. }
  473. if (doesntPass)
  474. continue;
  475. return true;
  476. }
  477. return false;
  478. }
  479. public override XPathItem CurrentCore {
  480. get { return left.Current; }
  481. }
  482. }
  483. // AxisIterator
  484. internal class AxisIterator : XPathSequence
  485. {
  486. NodeIterator iter;
  487. AxisStepExpr source;
  488. public AxisIterator (NodeIterator iter, AxisStepExpr source)
  489. : base (iter.Context)
  490. {
  491. this.iter = iter;
  492. this.source = source;
  493. }
  494. private AxisIterator (AxisIterator other)
  495. : base (other)
  496. {
  497. iter = (NodeIterator) other.iter.Clone ();
  498. source = other.source;
  499. }
  500. public override XPathSequence Clone ()
  501. {
  502. return new AxisIterator (this);
  503. }
  504. protected override bool MoveNextCore ()
  505. {
  506. while (iter.MoveNext ()) {
  507. if (source.Matches (iter.Current as XPathNavigator))
  508. return true;
  509. }
  510. return false;
  511. }
  512. public override XPathItem CurrentCore {
  513. get { return iter.Current; }
  514. }
  515. }
  516. internal abstract class NodeIterator : XPathSequence
  517. {
  518. XPathNavigator node;
  519. XPathNavigator current;
  520. bool emptyInput;
  521. public NodeIterator (XPathNavigator nav, XQueryContext ctx)
  522. : base (ctx)
  523. {
  524. this.node = nav.Clone ();
  525. }
  526. internal NodeIterator (NodeIterator other, bool cloneFlag)
  527. : base (other)
  528. {
  529. if (other.emptyInput)
  530. emptyInput = true;
  531. else
  532. node = other.node.Clone ();
  533. }
  534. internal XPathNavigator Node {
  535. get { return node; }
  536. }
  537. public override bool MoveNext ()
  538. {
  539. if (emptyInput)
  540. return false;
  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. }
  557. // <copy original='System.Xml.XPath/Iterator.cs'>
  558. internal class SelfIterator : NodeIterator
  559. {
  560. public SelfIterator (XPathNavigator nav, XQueryContext ctx)
  561. : base (nav, ctx)
  562. {
  563. }
  564. private SelfIterator (SelfIterator other, bool cloneFlag)
  565. : base (other, true)
  566. {
  567. }
  568. public override XPathSequence Clone ()
  569. {
  570. return new SelfIterator (this, true);
  571. }
  572. protected override bool MoveNextCore ()
  573. {
  574. if (Position == 0)
  575. return true;
  576. return false;
  577. }
  578. }
  579. internal class ParentIterator : NodeIterator
  580. {
  581. public ParentIterator (XPathNavigator nav, XQueryContext ctx)
  582. : base (nav, ctx)
  583. {
  584. }
  585. private ParentIterator (ParentIterator other, bool cloneFlag)
  586. : base (other, true)
  587. {
  588. }
  589. public override XPathSequence Clone ()
  590. {
  591. return new ParentIterator (this, true);
  592. }
  593. protected override bool MoveNextCore ()
  594. {
  595. if (Position == 0 && Node.MoveToParent ())
  596. return true;
  597. return false;
  598. }
  599. public override bool ReverseAxis {
  600. get { return true; }
  601. }
  602. }
  603. internal class ChildIterator : NodeIterator
  604. {
  605. public ChildIterator (XPathNavigator nav, XQueryContext ctx)
  606. : base (nav, ctx)
  607. {
  608. }
  609. private ChildIterator (ChildIterator other, bool cloneFlag)
  610. : base (other, true)
  611. {
  612. }
  613. public override XPathSequence Clone ()
  614. {
  615. return new ChildIterator (this, true);
  616. }
  617. protected override bool MoveNextCore ()
  618. {
  619. if (Position == 0)
  620. return Node.MoveToFirstChild ();
  621. else
  622. return Node.MoveToNext ();
  623. }
  624. }
  625. internal class FollowingSiblingIterator : NodeIterator
  626. {
  627. public FollowingSiblingIterator (XPathNavigator nav, XQueryContext ctx)
  628. : base (nav, ctx)
  629. {
  630. }
  631. private FollowingSiblingIterator (FollowingSiblingIterator other, bool cloneFlag)
  632. : base (other, true)
  633. {
  634. }
  635. public override XPathSequence Clone ()
  636. {
  637. return new FollowingSiblingIterator (this, true);
  638. }
  639. protected override bool MoveNextCore ()
  640. {
  641. return Node.MoveToNext ();
  642. }
  643. }
  644. internal class PrecedingSiblingIterator : NodeIterator
  645. {
  646. bool finished;
  647. bool started;
  648. XPathNavigator startPosition;
  649. public PrecedingSiblingIterator (XPathNavigator nav, XQueryContext ctx)
  650. : base (nav, ctx)
  651. {
  652. startPosition = Node.Clone ();
  653. }
  654. private PrecedingSiblingIterator (PrecedingSiblingIterator other, bool cloneFlag)
  655. : base (other, true)
  656. {
  657. startPosition = other.startPosition;
  658. started = other.started;
  659. finished = other.finished;
  660. }
  661. public override XPathSequence Clone ()
  662. {
  663. return new PrecedingSiblingIterator (this, true);
  664. }
  665. protected override bool MoveNextCore ()
  666. {
  667. if (finished)
  668. return false;
  669. if (!started) {
  670. started = true;
  671. Node.MoveToFirst ();
  672. } else {
  673. Node.MoveToNext ();
  674. }
  675. if (Node.ComparePosition (startPosition) == XmlNodeOrder.Same) {
  676. finished = true;
  677. return false;
  678. }
  679. else
  680. return true;
  681. }
  682. public override bool ReverseAxis {
  683. get { return true; }
  684. }
  685. }
  686. internal class AncestorIterator : NodeIterator
  687. {
  688. bool finished;
  689. ArrayList nodes = new ArrayList ();
  690. public AncestorIterator (XPathNavigator nav, XQueryContext ctx)
  691. : base (nav, ctx)
  692. {
  693. }
  694. private AncestorIterator (AncestorIterator other, bool cloneFlag)
  695. : base (other, true)
  696. {
  697. finished = other.finished;
  698. nodes = other.nodes;
  699. }
  700. public override XPathSequence Clone ()
  701. {
  702. return new AncestorIterator (this, true);
  703. }
  704. protected override bool MoveNextCore ()
  705. {
  706. if (finished)
  707. return false;
  708. if (nodes != null) {
  709. nodes = new ArrayList ();
  710. while (Node.MoveToParent () && Node.NodeType != XPathNodeType.Root)
  711. nodes.Add (Node.Clone ());
  712. nodes.Reverse ();
  713. }
  714. if (nodes.Count >= Position)
  715. return false;
  716. Node.MoveTo (nodes [Position] as XPathNavigator);
  717. return true;
  718. }
  719. public override bool ReverseAxis {
  720. get { return true; }
  721. }
  722. public override int Count {
  723. get {
  724. if (Position == 0)
  725. return base.Count;
  726. return nodes.Count;
  727. }
  728. }
  729. }
  730. internal class AncestorOrSelfIterator : NodeIterator
  731. {
  732. bool finished;
  733. ArrayList nodes = new ArrayList ();
  734. public AncestorOrSelfIterator (XPathNavigator nav, XQueryContext ctx)
  735. : base (nav, ctx)
  736. {
  737. }
  738. private AncestorOrSelfIterator (AncestorOrSelfIterator other, bool cloneFlag)
  739. : base (other, true)
  740. {
  741. finished = other.finished;
  742. nodes = other.nodes;
  743. }
  744. public override XPathSequence Clone ()
  745. {
  746. return new AncestorOrSelfIterator (this, true);
  747. }
  748. protected override bool MoveNextCore ()
  749. {
  750. if (finished)
  751. return false;
  752. if (nodes != null) {
  753. nodes = new ArrayList ();
  754. do {
  755. nodes.Add (Node.Clone ());
  756. } while (Node.MoveToParent () && Node.NodeType != XPathNodeType.Root);
  757. nodes.Reverse ();
  758. }
  759. if (nodes.Count >= Position)
  760. return false;
  761. Node.MoveTo (nodes [Position] as XPathNavigator);
  762. return true;
  763. }
  764. public override bool ReverseAxis {
  765. get { return true; }
  766. }
  767. public override int Count {
  768. get {
  769. if (Position == 0)
  770. return base.Count;
  771. return nodes.Count;
  772. }
  773. }
  774. }
  775. internal class DescendantIterator : NodeIterator
  776. {
  777. private int depth;
  778. private bool finished;
  779. public DescendantIterator (XPathNavigator nav, XQueryContext ctx)
  780. : base (nav, ctx)
  781. {
  782. }
  783. private DescendantIterator (DescendantIterator other, bool cloneFlag)
  784. : base (other, true)
  785. {
  786. finished = other.finished;
  787. depth = other.depth;
  788. }
  789. public override XPathSequence Clone ()
  790. {
  791. return new DescendantIterator (this, true);
  792. }
  793. protected override bool MoveNextCore ()
  794. {
  795. if (finished)
  796. return false;
  797. if (Node.MoveToFirstChild ()) {
  798. depth ++;
  799. return true;
  800. }
  801. while (depth != 0) {
  802. if (Node.MoveToNext ())
  803. return true;
  804. if (!Node.MoveToParent ()) // should NEVER fail!
  805. throw new XmlQueryException ("There seems some bugs on the XPathNavigator implementation class.");
  806. depth --;
  807. }
  808. finished = true;
  809. return false;
  810. }
  811. }
  812. internal class DescendantOrSelfIterator : NodeIterator
  813. {
  814. protected int depth;
  815. private bool finished;
  816. public DescendantOrSelfIterator (XPathNavigator nav, XQueryContext ctx)
  817. : base (nav, ctx)
  818. {
  819. }
  820. protected DescendantOrSelfIterator (DescendantOrSelfIterator other, bool cloneFlag)
  821. : base (other, true)
  822. {
  823. depth = other.depth;
  824. finished = other.finished;
  825. }
  826. public override XPathSequence Clone ()
  827. {
  828. return new DescendantOrSelfIterator (this, true);
  829. }
  830. protected override bool MoveNextCore ()
  831. {
  832. if (finished)
  833. return false;
  834. if (Position == 0)
  835. return true; // Self
  836. if (Node.MoveToFirstChild ()) {
  837. depth ++;
  838. return true;
  839. }
  840. while (depth != 0) {
  841. if (Node.MoveToNext ())
  842. return true;
  843. if (!Node.MoveToParent ()) // should NEVER fail!
  844. throw new XmlQueryException ("There seems some bugs on the XPathNavigator implementation class.");
  845. depth --;
  846. }
  847. finished = true;
  848. return false;
  849. }
  850. }
  851. internal class FollowingIterator : NodeIterator
  852. {
  853. private bool finished;
  854. public FollowingIterator (XPathNavigator nav, XQueryContext ctx)
  855. : base (nav, ctx)
  856. {
  857. }
  858. protected FollowingIterator (FollowingIterator other, bool cloneFlag)
  859. : base (other, true)
  860. {
  861. finished = other.finished;
  862. }
  863. public override XPathSequence Clone ()
  864. {
  865. return new FollowingIterator (this, true);
  866. }
  867. protected override bool MoveNextCore ()
  868. {
  869. if (finished)
  870. return false;
  871. if (Position == 0) {
  872. // At first, it should not iterate children.
  873. if (Node.MoveToNext ())
  874. return true;
  875. else {
  876. while (Node.MoveToParent ())
  877. if (Node.MoveToNext ())
  878. return true;
  879. }
  880. } else {
  881. if (Node.MoveToFirstChild ())
  882. return true;
  883. do {
  884. if (Node.MoveToNext ())
  885. return true;
  886. } while (Node.MoveToParent ());
  887. }
  888. finished = true;
  889. return false;
  890. }
  891. }
  892. internal class PrecedingIterator : NodeIterator
  893. {
  894. bool finished;
  895. bool started;
  896. XPathNavigator startPosition;
  897. public PrecedingIterator (XPathNavigator nav, XQueryContext ctx)
  898. : base (nav, ctx)
  899. {
  900. startPosition = Node.Clone ();
  901. }
  902. private PrecedingIterator (PrecedingIterator other, bool cloneFlag)
  903. : base (other, true)
  904. {
  905. startPosition = other.startPosition;
  906. started = other.started;
  907. finished = other.finished;
  908. }
  909. public override XPathSequence Clone ()
  910. {
  911. return new PrecedingIterator (this, true);
  912. }
  913. protected override bool MoveNextCore ()
  914. {
  915. if (finished)
  916. return false;
  917. if (!started) {
  918. started = true;
  919. Node.MoveToRoot ();
  920. }
  921. bool loop = true;
  922. while (loop) {
  923. while (!Node.MoveToFirstChild ()) {
  924. while (!Node.MoveToNext ()) {
  925. if (!Node.MoveToParent ()) { // Should not finish, at least before startPosition.
  926. finished = true;
  927. return false;
  928. }
  929. }
  930. break;
  931. }
  932. if (Node.IsDescendant (startPosition))
  933. continue;
  934. loop = false;
  935. break;
  936. }
  937. if (Node.ComparePosition (startPosition) != XmlNodeOrder.Before) {
  938. // Note that if _nav contains only 1 node, it won't be Same.
  939. finished = true;
  940. return false;
  941. }
  942. else
  943. return true;
  944. }
  945. public override bool ReverseAxis {
  946. get { return true; }
  947. }
  948. }
  949. internal class NamespaceIterator : NodeIterator
  950. {
  951. public NamespaceIterator (XPathNavigator nav, XQueryContext ctx)
  952. : base (nav, ctx)
  953. {
  954. }
  955. private NamespaceIterator (NamespaceIterator other, bool cloneFlag)
  956. : base (other, true)
  957. {
  958. }
  959. public override XPathSequence Clone ()
  960. {
  961. return new NamespaceIterator (this, true);
  962. }
  963. protected override bool MoveNextCore ()
  964. {
  965. if (Position == 0) {
  966. if (Node.MoveToFirstNamespace ())
  967. return true;
  968. }
  969. else if (Node.MoveToNextNamespace ())
  970. return true;
  971. return false;
  972. }
  973. public override bool ReverseAxis { get { return true; } }
  974. }
  975. internal class AttributeIterator : NodeIterator
  976. {
  977. public AttributeIterator (XPathNavigator nav, XQueryContext ctx)
  978. : base (nav, ctx)
  979. {
  980. }
  981. private AttributeIterator (AttributeIterator other, bool cloneFlag)
  982. : base (other, true)
  983. {
  984. }
  985. public override XPathSequence Clone ()
  986. {
  987. return new AttributeIterator (this, true);
  988. }
  989. protected override bool MoveNextCore ()
  990. {
  991. if (Position == 0) {
  992. if (Node.MoveToFirstAttribute ())
  993. return true;
  994. }
  995. else if (Node.MoveToNextAttribute ())
  996. return true;
  997. return false;
  998. }
  999. }
  1000. // </copy>
  1001. internal class ExprSequenceIterator : XPathSequence
  1002. {
  1003. XPathSequence contextSequence;
  1004. XPathSequence iter;
  1005. ExprSequence expr;
  1006. int currentExprIndex;
  1007. public ExprSequenceIterator (XPathSequence iter, ExprSequence expr)
  1008. : base (iter.Context)
  1009. {
  1010. contextSequence = iter;
  1011. this.expr = expr;
  1012. }
  1013. private ExprSequenceIterator (ExprSequenceIterator other)
  1014. : base (other)
  1015. {
  1016. if (other.iter != null)
  1017. iter = other.iter.Clone ();
  1018. expr = other.expr;
  1019. contextSequence = other.contextSequence;
  1020. currentExprIndex = other.currentExprIndex;
  1021. }
  1022. public override XPathSequence Clone ()
  1023. {
  1024. return new ExprSequenceIterator (this);
  1025. }
  1026. protected override bool MoveNextCore ()
  1027. {
  1028. if (iter != null && iter.MoveNext ())
  1029. return true;
  1030. while (currentExprIndex < expr.Count) {
  1031. iter = expr [currentExprIndex++].Evaluate (contextSequence);
  1032. if (iter.MoveNext ())
  1033. return true;
  1034. }
  1035. return false;
  1036. }
  1037. public override XPathItem CurrentCore {
  1038. get { return iter.Current; }
  1039. }
  1040. }
  1041. // FLWOR - Order By
  1042. internal class FLWORIterator : XPathSequence
  1043. {
  1044. XPathSequence contextSequence;
  1045. FLWORExpr expr;
  1046. ArrayList forStack = new ArrayList ();
  1047. IEnumerator en;
  1048. bool finished;
  1049. public FLWORIterator (XPathSequence iter, FLWORExpr expr)
  1050. : base (iter.Context)
  1051. {
  1052. this.contextSequence = iter;
  1053. this.expr = expr;
  1054. }
  1055. private FLWORIterator (FLWORIterator other)
  1056. : base (other)
  1057. {
  1058. contextSequence = other.contextSequence;
  1059. expr = other.expr;
  1060. forStack = other.forStack.Clone () as ArrayList;
  1061. if (en != null)
  1062. en = ((ICloneable) other.en).Clone () as IEnumerator;
  1063. finished = other.finished;
  1064. }
  1065. public override XPathSequence Clone ()
  1066. {
  1067. return new FLWORIterator (this);
  1068. }
  1069. protected override bool MoveNextCore ()
  1070. {
  1071. if (en == null)
  1072. en = GetEnumerator ();
  1073. return en.MoveNext ();
  1074. }
  1075. public override IEnumerator GetEnumerator ()
  1076. {
  1077. return EvaluateRemainingForLet (0);
  1078. }
  1079. private IEnumerator EvaluateRemainingForLet (int flcPosition)
  1080. {
  1081. // Prepare iteration stack
  1082. if (flcPosition < expr.ForLetClauses.Count) {
  1083. IEnumerator items = EvaluateRemainingSingleItem (flcPosition, 0);
  1084. while (items.MoveNext ())
  1085. yield return items.Current;
  1086. } else {
  1087. bool passedFilter = expr.WhereClause == null;
  1088. if (!passedFilter)
  1089. passedFilter = expr.WhereClause.EvaluateAsBoolean (contextSequence);
  1090. if (passedFilter) {
  1091. IEnumerator ie = expr.ReturnExpr.Evaluate (contextSequence).GetEnumerator ();
  1092. while (ie.MoveNext ())
  1093. yield return (XPathItem) ie.Current;
  1094. }
  1095. }
  1096. }
  1097. private IEnumerator EvaluateRemainingSingleItem (int flcPosition, int singlePosition)
  1098. {
  1099. if (singlePosition < expr.ForLetClauses [flcPosition].Count) {
  1100. ForLetSingleBody sb = expr.ForLetClauses [flcPosition] [singlePosition];
  1101. ForSingleBody fsb = sb as ForSingleBody;
  1102. if (fsb != null) {
  1103. XPathSequence backup = contextSequence;
  1104. contextSequence = fsb.Expression.Evaluate (Context.CurrentSequence);
  1105. Context.ContextManager.PushCurrentSequence (contextSequence);
  1106. while (contextSequence.MoveNext ()) {
  1107. XPathItem forItem = (XPathItem) contextSequence.Current;
  1108. Context.PushVariable (fsb.PositionalVar, contextSequence.Position);
  1109. Context.PushVariable (sb.VarName, forItem);
  1110. // recurse here (including following bindings)
  1111. IEnumerator items = EvaluateRemainingSingleItem (flcPosition, singlePosition + 1);
  1112. while (items.MoveNext ())
  1113. yield return (XPathItem) items.Current;
  1114. Context.PopVariable ();
  1115. Context.PopVariable ();
  1116. }
  1117. Context.ContextManager.PopCurrentSequence ();
  1118. contextSequence = backup;
  1119. } else {
  1120. Context.PushVariable (sb.VarName, sb.Expression.Evaluate (contextSequence));
  1121. // recurse here (including following bindings)
  1122. IEnumerator items = EvaluateRemainingSingleItem (flcPosition, singlePosition + 1);
  1123. while (items.MoveNext ())
  1124. yield return (XPathItem) items.Current;
  1125. Context.PopVariable ();
  1126. }
  1127. } else {
  1128. // evaluate next binding
  1129. IEnumerator items = EvaluateRemainingForLet (flcPosition + 1);
  1130. while (items.MoveNext ())
  1131. yield return (XPathItem) items.Current;
  1132. }
  1133. }
  1134. public override XPathItem CurrentCore {
  1135. get { return (XPathItem) en.Current; }
  1136. }
  1137. }
  1138. internal class GroupIterator : XPathSequence
  1139. {
  1140. GroupExpr expr;
  1141. XPathSequence lseq;
  1142. XPathSequence rseq;
  1143. bool started;
  1144. bool left;
  1145. bool leftFinished;
  1146. bool rightFinished;
  1147. public GroupIterator (XPathSequence iter, GroupExpr expr)
  1148. : base (iter.Context)
  1149. {
  1150. this.expr = expr;
  1151. left = true;
  1152. lseq = expr.Left.EvaluateOrdered (iter);
  1153. rseq = expr.Right.EvaluateOrdered (iter);
  1154. }
  1155. private GroupIterator (GroupIterator other)
  1156. : base (other)
  1157. {
  1158. this.expr = other.expr;
  1159. this.started = other.started;
  1160. this.left = other.left;
  1161. this.leftFinished = other.leftFinished;
  1162. this.rightFinished = other.rightFinished;
  1163. this.lseq = other.lseq.Clone ();
  1164. this.rseq = other.rseq.Clone ();
  1165. }
  1166. public override XPathSequence Clone ()
  1167. {
  1168. return new GroupIterator (this);
  1169. }
  1170. protected override bool MoveNextCore ()
  1171. {
  1172. if (leftFinished && rightFinished)
  1173. return false;
  1174. bool proceeded = false;
  1175. if (started) {
  1176. if (left) {
  1177. if (!leftFinished && lseq.MoveNext ())
  1178. proceeded = true;
  1179. else
  1180. leftFinished = true;
  1181. } else {
  1182. if (rightFinished && rseq.MoveNext ())
  1183. proceeded = true;
  1184. else
  1185. rightFinished = true;
  1186. }
  1187. } else {
  1188. started = true;
  1189. if (!lseq.MoveNext ()) {
  1190. leftFinished = true;
  1191. if (!rseq.MoveNext ()) {
  1192. rightFinished = true;
  1193. return false;
  1194. }
  1195. left = false;
  1196. return true;
  1197. }
  1198. proceeded = true;
  1199. if (!rseq.MoveNext ()) {
  1200. rightFinished = true;
  1201. return true;
  1202. }
  1203. }
  1204. if (!proceeded) {
  1205. if (expr.AggregationType == AggregationType.Intersect)
  1206. return false;
  1207. left = !leftFinished;
  1208. return !leftFinished || !rightFinished;
  1209. }
  1210. XPathNavigator lnav = lseq.Current as XPathNavigator;
  1211. XPathNavigator rnav = rseq.Current as XPathNavigator;
  1212. if (lnav == null || rnav == null)
  1213. throw new XmlQueryException ("XP0006: Evaluation against union, intersect, except expressions must result in nodes.");
  1214. XmlNodeOrder order = lnav.ComparePosition (rnav);
  1215. switch (order) {
  1216. case XmlNodeOrder.Same:
  1217. switch (expr.AggregationType) {
  1218. case AggregationType.Union:
  1219. left = false;
  1220. if (!lseq.MoveNext ())
  1221. leftFinished = true;
  1222. return true;
  1223. case AggregationType.Intersect:
  1224. return true;
  1225. case AggregationType.Except:
  1226. default:
  1227. return MoveNext ();
  1228. }
  1229. case XmlNodeOrder.Before:
  1230. left = true;
  1231. if (expr.AggregationType == AggregationType.Intersect)
  1232. return MoveNext ();
  1233. return true;
  1234. default: // After, Unknown
  1235. left = false;
  1236. if (expr.AggregationType == AggregationType.Intersect)
  1237. return MoveNext ();
  1238. return true;
  1239. }
  1240. }
  1241. public override XPathItem CurrentCore {
  1242. get { return left ? lseq.Current : rseq.Current; }
  1243. }
  1244. }
  1245. internal class AtomizingIterator : XPathSequence
  1246. {
  1247. XPathSequence iter;
  1248. public AtomizingIterator (XPathSequence iter)
  1249. : base (iter.Context)
  1250. {
  1251. this.iter = iter;
  1252. }
  1253. private AtomizingIterator (AtomizingIterator other)
  1254. : base (other)
  1255. {
  1256. iter = other.iter.Clone ();
  1257. }
  1258. public override XPathSequence Clone ()
  1259. {
  1260. return new AtomizingIterator (this);
  1261. }
  1262. protected override bool MoveNextCore ()
  1263. {
  1264. return iter.MoveNext ();
  1265. }
  1266. public override XPathItem CurrentCore {
  1267. get {
  1268. XPathNavigator nav = iter.Current as XPathNavigator;
  1269. if (nav == null)
  1270. return (XPathAtomicValue) iter.Current;
  1271. if (nav.SchemaInfo != null)
  1272. return new XPathAtomicValue (
  1273. nav.TypedValue,
  1274. nav.SchemaInfo.SchemaType);
  1275. else
  1276. return new XPathAtomicValue (nav.Value, null);
  1277. }
  1278. }
  1279. }
  1280. internal class ConvertingIterator : XPathSequence
  1281. {
  1282. XPathSequence iter;
  1283. SequenceType type;
  1284. public ConvertingIterator (XPathSequence iter, SequenceType type)
  1285. : base (iter.Context)
  1286. {
  1287. this.iter = iter;
  1288. this.type = type;
  1289. }
  1290. private ConvertingIterator (ConvertingIterator other)
  1291. : base (other)
  1292. {
  1293. iter = other.iter.Clone ();
  1294. type = other.type;
  1295. }
  1296. public override XPathSequence Clone ()
  1297. {
  1298. return new ConvertingIterator (this);
  1299. }
  1300. protected override bool MoveNextCore ()
  1301. {
  1302. return iter.MoveNext ();
  1303. }
  1304. public override XPathItem CurrentCore {
  1305. get { return type.Convert (iter.Current); }
  1306. }
  1307. }
  1308. internal class TracingIterator : XPathSequence
  1309. {
  1310. XPathSequence iter;
  1311. string format;
  1312. public TracingIterator (XPathSequence iter, string format)
  1313. : base (iter.Context)
  1314. {
  1315. this.iter = iter;
  1316. this.format = format;
  1317. }
  1318. private TracingIterator (TracingIterator other)
  1319. : base (other)
  1320. {
  1321. iter = other.iter.Clone ();
  1322. format = other.format;
  1323. }
  1324. public override XPathSequence Clone ()
  1325. {
  1326. return new TracingIterator (this);
  1327. }
  1328. protected override bool MoveNextCore ()
  1329. {
  1330. if (!iter.MoveNext ())
  1331. return false;
  1332. // FIXME: use OnMessageEvent
  1333. string output = String.Format (format, iter.Current.TypedValue);
  1334. Context.StaticContext.OnMessageEvent (iter.Current, new TraceEventArgs (output));
  1335. return true;
  1336. }
  1337. public override XPathItem CurrentCore {
  1338. get { return iter.Current; }
  1339. }
  1340. internal class TraceEventArgs : QueryEventArgs
  1341. {
  1342. string message;
  1343. internal TraceEventArgs (string message)
  1344. {
  1345. this.message = message;
  1346. }
  1347. public override string Message {
  1348. get { return message; }
  1349. }
  1350. }
  1351. }
  1352. internal class ListIterator : XPathSequence
  1353. {
  1354. IList list;
  1355. public ListIterator (XQueryContext ctx, IList list)
  1356. : base (ctx)
  1357. {
  1358. if (list is ICloneable)
  1359. this.list = list;
  1360. else
  1361. throw new InvalidOperationException (String.Format ("XQuery internal error: target list is not cloneable. List is {0}.", list != null ? list.GetType ().ToString () : "null argument"));
  1362. }
  1363. private ListIterator (ListIterator other)
  1364. : base (other)
  1365. {
  1366. this.list = (IList) ((ICloneable) other.list).Clone ();
  1367. }
  1368. public override XPathSequence Clone ()
  1369. {
  1370. return new ListIterator (this);
  1371. }
  1372. protected override bool MoveNextCore ()
  1373. {
  1374. return (Position < list.Count);
  1375. }
  1376. public override XPathItem CurrentCore {
  1377. get { return (XPathItem) list [Position - 1]; }
  1378. }
  1379. }
  1380. internal class EnumeratorIterator : XPathSequence
  1381. {
  1382. IEnumerator list;
  1383. public EnumeratorIterator (XQueryContext ctx, IEnumerable en)
  1384. : base (ctx)
  1385. {
  1386. list = en.GetEnumerator ();
  1387. if (list is ICloneable)
  1388. this.list = list;
  1389. else
  1390. 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"));
  1391. }
  1392. private EnumeratorIterator (EnumeratorIterator other)
  1393. : base (other)
  1394. {
  1395. this.list = (IEnumerator) ((ICloneable) other.list).Clone ();
  1396. }
  1397. public override XPathSequence Clone ()
  1398. {
  1399. return new EnumeratorIterator (this);
  1400. }
  1401. protected override bool MoveNextCore ()
  1402. {
  1403. return list.MoveNext ();
  1404. }
  1405. public override XPathItem CurrentCore {
  1406. get { return (XPathItem) list.Current; }
  1407. }
  1408. }
  1409. internal abstract class WrapperIterator : XPathSequence
  1410. {
  1411. XPathSequence source;
  1412. public WrapperIterator (XPathSequence source)
  1413. : base (source.Context)
  1414. {
  1415. this.source = source;
  1416. }
  1417. protected WrapperIterator (WrapperIterator other, bool flag)
  1418. : base (other)
  1419. {
  1420. source = other.source.Clone ();
  1421. }
  1422. public XPathSequence Source {
  1423. get { return source; }
  1424. }
  1425. public override XPathItem CurrentCore {
  1426. get { return source.Current; }
  1427. }
  1428. }
  1429. internal class RemovalIterator : WrapperIterator
  1430. {
  1431. int position;
  1432. public RemovalIterator (XPathSequence source, int position)
  1433. : base (source)
  1434. {
  1435. this.position = position;
  1436. }
  1437. protected RemovalIterator (RemovalIterator other)
  1438. : base (other, true)
  1439. {
  1440. position = other.position;
  1441. }
  1442. public override XPathSequence Clone ()
  1443. {
  1444. return new RemovalIterator (this);
  1445. }
  1446. protected override bool MoveNextCore ()
  1447. {
  1448. if (!Source.MoveNext ())
  1449. return false;
  1450. else if (Source.Position == position) // skip target
  1451. return Source.MoveNext ();
  1452. else
  1453. return true;
  1454. }
  1455. }
  1456. internal class InsertingIterator : WrapperIterator
  1457. {
  1458. int position;
  1459. XPathSequence inserts;
  1460. bool sourceFinished;
  1461. bool insertsFinished;
  1462. XPathSequence currentSequence;
  1463. public InsertingIterator (XPathSequence target, int position, XPathSequence inserts)
  1464. : base (target)
  1465. {
  1466. this.position = position;
  1467. this.inserts = inserts;
  1468. currentSequence = target;
  1469. }
  1470. protected InsertingIterator (InsertingIterator other)
  1471. : base (other)
  1472. {
  1473. position = other.position;
  1474. inserts = other.inserts.Clone ();
  1475. sourceFinished = other.sourceFinished;
  1476. insertsFinished = other.insertsFinished;
  1477. currentSequence =
  1478. other.inserts == other.currentSequence ?
  1479. inserts : Source;
  1480. }
  1481. public override XPathSequence Clone ()
  1482. {
  1483. return new InsertingIterator (this);
  1484. }
  1485. protected override bool MoveNextCore ()
  1486. {
  1487. if (insertsFinished && sourceFinished)
  1488. return false;
  1489. if (sourceFinished) { // position >= source.Count
  1490. currentSequence = inserts;
  1491. if (inserts.MoveNext ())
  1492. return true;
  1493. insertsFinished = true;
  1494. return false;
  1495. }
  1496. else if (insertsFinished) { // after insertion
  1497. if (Source.MoveNext ())
  1498. return true;
  1499. sourceFinished = true;
  1500. return false;
  1501. }
  1502. else if (Position >= position - 1) {
  1503. currentSequence = inserts;
  1504. if (inserts.MoveNext ())
  1505. return true;
  1506. currentSequence = Source;
  1507. insertsFinished = true;
  1508. }
  1509. if (Source.MoveNext ())
  1510. return true;
  1511. sourceFinished = true;
  1512. return MoveNextCore ();
  1513. }
  1514. public override XPathItem CurrentCore {
  1515. get { return currentSequence.Current; }
  1516. }
  1517. }
  1518. internal class DistinctValueIterator : XPathSequence
  1519. {
  1520. XPathSequence items;
  1521. CultureInfo collation;
  1522. Hashtable table = new Hashtable ();
  1523. public DistinctValueIterator (XQueryContext ctx, XPathSequence items, CultureInfo collation)
  1524. : base (ctx)
  1525. {
  1526. this.items = items;
  1527. this.collation = collation;
  1528. }
  1529. protected DistinctValueIterator (DistinctValueIterator other)
  1530. : base (other)
  1531. {
  1532. items = other.items.Clone ();
  1533. collation = other.collation;
  1534. table = (Hashtable) other.table.Clone ();
  1535. }
  1536. public override XPathSequence Clone ()
  1537. {
  1538. return new DistinctValueIterator (this);
  1539. }
  1540. protected override bool MoveNextCore ()
  1541. {
  1542. if (!items.MoveNext ())
  1543. return false;
  1544. // FIXME: use collations
  1545. // FIXME: check if it really works (esp. Uri et.al)
  1546. if (table.Contains (items.Current.TypedValue))
  1547. return MoveNextCore ();
  1548. return true;
  1549. }
  1550. public override XPathItem CurrentCore {
  1551. get { return items.Current; }
  1552. }
  1553. }
  1554. }
  1555. #endif