QueryNode.cs 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Dispatcher
  5. {
  6. using System;
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using System.Runtime;
  10. using System.Threading;
  11. using System.Xml;
  12. using System.Xml.XPath;
  13. /// <summary>
  14. /// A navigator is a cursor over the nodes in a DOM, where each node is assigned a unique position.
  15. /// A node is a (navigator, position) pair.
  16. /// </summary>
  17. internal struct QueryNode
  18. {
  19. SeekableXPathNavigator node;
  20. long nodePosition;
  21. /// <summary>
  22. /// Create a query node from the given navigator and its current position
  23. /// </summary>
  24. /// <param name="node"></param>
  25. internal QueryNode(SeekableXPathNavigator node)
  26. {
  27. this.node = node;
  28. this.nodePosition = node.CurrentPosition;
  29. }
  30. /// <summary>
  31. /// Initialize using the given (node, position) pair
  32. /// </summary>
  33. #if NO
  34. internal QueryNode(SeekableXPathNavigator node, long nodePosition)
  35. {
  36. this.node = node;
  37. this.nodePosition = nodePosition;
  38. }
  39. #endif
  40. internal string LocalName
  41. {
  42. get
  43. {
  44. return this.node.GetLocalName(this.nodePosition);
  45. }
  46. }
  47. /// <summary>
  48. /// Return the node's name
  49. /// </summary>
  50. internal string Name
  51. {
  52. get
  53. {
  54. return this.node.GetName(this.nodePosition);
  55. }
  56. }
  57. /// <summary>
  58. /// Return the node's namespace
  59. /// </summary>
  60. internal string Namespace
  61. {
  62. get
  63. {
  64. return this.node.GetNamespace(this.nodePosition);
  65. }
  66. }
  67. /// <summary>
  68. /// Return this query node's underlying Node
  69. /// </summary>
  70. internal SeekableXPathNavigator Node
  71. {
  72. get
  73. {
  74. return this.node;
  75. }
  76. }
  77. /// <summary>
  78. ///
  79. /// </summary>
  80. internal long Position
  81. {
  82. get
  83. {
  84. return this.nodePosition;
  85. }
  86. }
  87. #if NO
  88. /// <summary>
  89. /// This node's type
  90. /// </summary>
  91. internal QueryNodeType Type
  92. {
  93. get
  94. {
  95. return QueryDataModel.GetNodeType(this.node.GetNodeType(this.nodePosition));
  96. }
  97. }
  98. #endif
  99. /// <summary>
  100. /// This node's string value
  101. /// </summary>
  102. internal string Value
  103. {
  104. get
  105. {
  106. return this.node.GetValue(this.nodePosition);
  107. }
  108. }
  109. #if NO
  110. /// <summary>
  111. /// Raw xpath node type
  112. /// </summary>
  113. internal XPathNodeType XPathNodeType
  114. {
  115. get
  116. {
  117. return this.node.GetNodeType(this.nodePosition);
  118. }
  119. }
  120. #endif
  121. /// <summary>
  122. /// Move this node's navigator to its position
  123. /// </summary>
  124. /// <returns></returns>
  125. internal SeekableXPathNavigator MoveTo()
  126. {
  127. this.node.CurrentPosition = this.nodePosition;
  128. return this.node;
  129. }
  130. }
  131. internal enum NodeSequenceItemFlags : byte
  132. {
  133. None = 0x00,
  134. NodesetLast = 0x01,
  135. }
  136. // PERF, [....], Remove when generic sort works
  137. // Used to sort in document order
  138. #if NO
  139. internal class NodeSequenceItemObjectComparer : IComparer
  140. {
  141. internal NodeSequenceItemObjectComparer()
  142. {
  143. }
  144. public int Compare(object obj1, object obj2)
  145. {
  146. NodeSequenceItem item1 = (NodeSequenceItem)obj1;
  147. NodeSequenceItem item2 = (NodeSequenceItem)obj2;
  148. XmlNodeOrder order = item1.Node.Node.ComparePosition(item1.Node.Position, item2.Node.Position);
  149. int ret;
  150. switch(order)
  151. {
  152. case XmlNodeOrder.Before:
  153. ret = -1;
  154. break;
  155. case XmlNodeOrder.Same:
  156. ret = 0;
  157. break;
  158. case XmlNodeOrder.After:
  159. ret = 1;
  160. break;
  161. case XmlNodeOrder.Unknown:
  162. default:
  163. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XPathException(SR.GetString(SR.QueryNotSortable)), TraceEventType.Critical);
  164. }
  165. return ret;
  166. }
  167. }
  168. // Used to sort in document order
  169. internal class NodeSequenceItemComparer : IComparer<NodeSequenceItem>
  170. {
  171. internal NodeSequenceItemComparer()
  172. {
  173. }
  174. public int Compare(NodeSequenceItem item1, NodeSequenceItem item2)
  175. {
  176. XmlNodeOrder order = item1.Node.Node.ComparePosition(item1.Node.Position, item2.Node.Position);
  177. int ret;
  178. switch(order)
  179. {
  180. case XmlNodeOrder.Before:
  181. ret = -1;
  182. break;
  183. case XmlNodeOrder.Same:
  184. ret = 0;
  185. break;
  186. case XmlNodeOrder.After:
  187. ret = 1;
  188. break;
  189. case XmlNodeOrder.Unknown:
  190. default:
  191. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XPathException(SR.GetString(SR.QueryNotSortable)), TraceEventType.Critical);
  192. }
  193. return ret;
  194. }
  195. public bool Equals(NodeSequenceItem item1, NodeSequenceItem item2)
  196. {
  197. return Compare(item1, item2) == 0;
  198. }
  199. public int GetHashCode(NodeSequenceItem item)
  200. {
  201. return item.GetHashCode();
  202. }
  203. }
  204. #endif
  205. // Used to sort in document order
  206. internal class QueryNodeComparer : IComparer<QueryNode>
  207. {
  208. public QueryNodeComparer()
  209. {
  210. }
  211. public int Compare(QueryNode item1, QueryNode item2)
  212. {
  213. XmlNodeOrder order = item1.Node.ComparePosition(item1.Position, item2.Position);
  214. int ret;
  215. switch (order)
  216. {
  217. case XmlNodeOrder.Before:
  218. ret = -1;
  219. break;
  220. case XmlNodeOrder.Same:
  221. ret = 0;
  222. break;
  223. case XmlNodeOrder.After:
  224. ret = 1;
  225. break;
  226. case XmlNodeOrder.Unknown:
  227. default:
  228. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new XPathException(SR.GetString(SR.QueryNotSortable)));
  229. }
  230. return ret;
  231. }
  232. public bool Equals(QueryNode item1, QueryNode item2)
  233. {
  234. return Compare(item1, item2) == 0;
  235. }
  236. public int GetHashCode(QueryNode item)
  237. {
  238. return item.GetHashCode();
  239. }
  240. }
  241. internal struct NodeSequenceItem
  242. {
  243. NodeSequenceItemFlags flags;
  244. QueryNode node;
  245. int position;
  246. int size;
  247. internal NodeSequenceItemFlags Flags
  248. {
  249. get
  250. {
  251. return this.flags;
  252. }
  253. set
  254. {
  255. this.flags = value;
  256. }
  257. }
  258. internal bool Last
  259. {
  260. get
  261. {
  262. return (0 != (NodeSequenceItemFlags.NodesetLast & this.flags));
  263. }
  264. set
  265. {
  266. if (value)
  267. {
  268. this.flags |= NodeSequenceItemFlags.NodesetLast;
  269. }
  270. else
  271. {
  272. this.flags &= ~(NodeSequenceItemFlags.NodesetLast);
  273. }
  274. }
  275. }
  276. internal string LocalName
  277. {
  278. get
  279. {
  280. return this.node.LocalName;
  281. }
  282. }
  283. internal string Name
  284. {
  285. get
  286. {
  287. return this.node.Name;
  288. }
  289. }
  290. internal string Namespace
  291. {
  292. get
  293. {
  294. return this.node.Namespace;
  295. }
  296. }
  297. internal QueryNode Node
  298. {
  299. get
  300. {
  301. return this.node;
  302. }
  303. #if NO
  304. set
  305. {
  306. this.node = value;
  307. }
  308. #endif
  309. }
  310. internal int Position
  311. {
  312. get
  313. {
  314. return this.position;
  315. }
  316. #if NO
  317. set
  318. {
  319. this.position = value;
  320. }
  321. #endif
  322. }
  323. internal int Size
  324. {
  325. get
  326. {
  327. return this.size;
  328. }
  329. set
  330. {
  331. this.size = value;
  332. }
  333. }
  334. internal bool Compare(double dblVal, RelationOperator op)
  335. {
  336. return QueryValueModel.Compare(this.NumberValue(), dblVal, op);
  337. }
  338. internal bool Compare(string strVal, RelationOperator op)
  339. {
  340. return QueryValueModel.Compare(this.StringValue(), strVal, op);
  341. }
  342. internal bool Compare(ref NodeSequenceItem item, RelationOperator op)
  343. {
  344. return QueryValueModel.Compare(this.StringValue(), item.StringValue(), op);
  345. }
  346. internal bool Equals(string literal)
  347. {
  348. return QueryValueModel.Equals(this.StringValue(), literal);
  349. }
  350. internal bool Equals(double literal)
  351. {
  352. return (this.NumberValue() == literal);
  353. }
  354. internal SeekableXPathNavigator GetNavigator()
  355. {
  356. return this.node.MoveTo();
  357. }
  358. internal long GetNavigatorPosition()
  359. {
  360. return this.node.Position;
  361. }
  362. internal double NumberValue()
  363. {
  364. return QueryValueModel.Double(this.StringValue());
  365. }
  366. internal void Set(SeekableXPathNavigator node, int position, int size)
  367. {
  368. Fx.Assert(position > 0, "");
  369. Fx.Assert(null != node, "");
  370. this.node = new QueryNode(node);
  371. this.position = position;
  372. this.size = size;
  373. this.flags = NodeSequenceItemFlags.None;
  374. }
  375. internal void Set(QueryNode node, int position, int size)
  376. {
  377. Fx.Assert(position > 0, "");
  378. this.node = node;
  379. this.position = position;
  380. this.size = size;
  381. this.flags = NodeSequenceItemFlags.None;
  382. }
  383. internal void Set(ref NodeSequenceItem item, int position, int size)
  384. {
  385. Fx.Assert(position > 0, "");
  386. this.node = item.node;
  387. this.position = position;
  388. this.size = size;
  389. this.flags = item.flags;
  390. }
  391. internal void SetPositionAndSize(int position, int size)
  392. {
  393. this.position = position;
  394. this.size = size;
  395. this.flags &= ~NodeSequenceItemFlags.NodesetLast;
  396. }
  397. internal void SetSizeAndLast()
  398. {
  399. this.size = 1;
  400. this.flags |= NodeSequenceItemFlags.NodesetLast;
  401. }
  402. // This is not optimized right now
  403. // We may want to CACHE string values once they are computed
  404. internal string StringValue()
  405. {
  406. return this.node.Value;
  407. }
  408. }
  409. internal class NodeSequence
  410. {
  411. #if DEBUG
  412. // debugging aid. Because C# references do not have displayble numeric values, hard to deduce the
  413. // graph structure to see what opcode is connected to what
  414. static long nextUniqueId = 0;
  415. internal long uniqueID;
  416. #endif
  417. int count;
  418. internal static NodeSequence Empty = new NodeSequence(0);
  419. NodeSequenceItem[] items;
  420. NodeSequence next;
  421. ProcessingContext ownerContext;
  422. int position;
  423. internal int refCount;
  424. int sizePosition;
  425. static readonly QueryNodeComparer staticQueryNodeComparerInstance = new QueryNodeComparer();
  426. internal NodeSequence()
  427. : this(8, null)
  428. {
  429. }
  430. internal NodeSequence(int capacity)
  431. : this(capacity, null)
  432. {
  433. }
  434. internal NodeSequence(int capacity, ProcessingContext ownerContext)
  435. {
  436. this.items = new NodeSequenceItem[capacity];
  437. this.ownerContext = ownerContext;
  438. #if DEBUG
  439. this.uniqueID = Interlocked.Increment(ref NodeSequence.nextUniqueId);
  440. #endif
  441. }
  442. #if NO
  443. internal NodeSequence(int capacity, ProcessingContext ownerContext, XPathNodeIterator iter)
  444. : this(capacity, ownerContext)
  445. {
  446. while(iter.MoveNext())
  447. {
  448. SeekableXPathNavigator nav = iter.Current as SeekableXPathNavigator;
  449. if(nav != null)
  450. {
  451. Add(nav);
  452. }
  453. else
  454. {
  455. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryProcessingException(QueryProcessingError.Unexpected, SR.GetString(SR.QueryMustBeSeekable)), TraceEventType.Critical);
  456. }
  457. }
  458. }
  459. #endif
  460. internal int Count
  461. {
  462. get
  463. {
  464. return this.count;
  465. }
  466. #if NO
  467. set
  468. {
  469. Fx.Assert(value >= 0 && value <= this.count, "");
  470. this.count = value;
  471. }
  472. #endif
  473. }
  474. internal NodeSequenceItem this[int index]
  475. {
  476. get
  477. {
  478. return this.items[index];
  479. }
  480. }
  481. internal NodeSequenceItem[] Items
  482. {
  483. get
  484. {
  485. return this.items;
  486. }
  487. }
  488. internal bool IsNotEmpty
  489. {
  490. get
  491. {
  492. return (this.count > 0);
  493. }
  494. }
  495. internal string LocalName
  496. {
  497. get
  498. {
  499. if (this.count > 0)
  500. {
  501. return this.items[0].LocalName;
  502. }
  503. return string.Empty;
  504. }
  505. }
  506. internal string Name
  507. {
  508. get
  509. {
  510. if (this.count > 0)
  511. {
  512. return this.items[0].Name;
  513. }
  514. return string.Empty;
  515. }
  516. }
  517. internal string Namespace
  518. {
  519. get
  520. {
  521. if (this.count > 0)
  522. {
  523. return this.items[0].Namespace;
  524. }
  525. return string.Empty;
  526. }
  527. }
  528. internal NodeSequence Next
  529. {
  530. get
  531. {
  532. return this.next;
  533. }
  534. set
  535. {
  536. this.next = value;
  537. }
  538. }
  539. internal ProcessingContext OwnerContext
  540. {
  541. get
  542. {
  543. return this.ownerContext;
  544. }
  545. set
  546. {
  547. this.ownerContext = value;
  548. }
  549. }
  550. #if NO
  551. internal int NodesetStartAt
  552. {
  553. get
  554. {
  555. return -this.sizePosition;
  556. }
  557. }
  558. #endif
  559. internal void Add(XPathNodeIterator iter)
  560. {
  561. while (iter.MoveNext())
  562. {
  563. SeekableXPathNavigator nav = iter.Current as SeekableXPathNavigator;
  564. if (nav != null)
  565. {
  566. this.Add(nav);
  567. }
  568. else
  569. {
  570. throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.Unexpected, SR.GetString(SR.QueryMustBeSeekable)));
  571. }
  572. }
  573. }
  574. internal void Add(SeekableXPathNavigator node)
  575. {
  576. Fx.Assert(this.items.Length > 0, "");
  577. if (this.count == this.items.Length)
  578. {
  579. this.Grow(this.items.Length * 2);
  580. }
  581. this.position++;
  582. this.items[this.count++].Set(node, this.position, this.sizePosition);
  583. }
  584. internal void Add(QueryNode node)
  585. {
  586. Fx.Assert(this.items.Length > 0, "");
  587. if (this.count == this.items.Length)
  588. {
  589. this.Grow(this.items.Length * 2);
  590. }
  591. this.position++;
  592. this.items[this.count++].Set(node, this.position, this.sizePosition);
  593. }
  594. internal void Add(ref NodeSequenceItem item)
  595. {
  596. Fx.Assert(this.items.Length > 0, "");
  597. if (this.count == this.items.Length)
  598. {
  599. this.Grow(this.items.Length * 2);
  600. }
  601. this.position++;
  602. this.items[this.count++].Set(ref item, this.position, this.sizePosition);
  603. }
  604. internal void AddCopy(ref NodeSequenceItem item, int size)
  605. {
  606. Fx.Assert(this.items.Length > 0, "");
  607. if (this.count == this.items.Length)
  608. {
  609. this.Grow(this.items.Length * 2);
  610. }
  611. this.items[this.count] = item;
  612. this.items[this.count++].Size = size;
  613. }
  614. internal void AddCopy(ref NodeSequenceItem item)
  615. {
  616. Fx.Assert(this.items.Length > 0, "");
  617. if (this.count == this.items.Length)
  618. {
  619. this.Grow(this.items.Length * 2);
  620. }
  621. this.items[this.count++] = item;
  622. }
  623. #if NO
  624. internal void Add(NodeSequence seq)
  625. {
  626. int newCount = this.count + seq.count;
  627. if (newCount > this.items.Length)
  628. {
  629. // We are going to need room. Grow the array
  630. int growTo = this.items.Length * 2;
  631. this.Grow(newCount > growTo ? newCount : growTo);
  632. }
  633. Array.Copy(seq.items, 0, this.items, this.count, seq.count);
  634. this.count += seq.count;
  635. }
  636. #endif
  637. internal bool CanReuse(ProcessingContext context)
  638. {
  639. return (this.count == 1 && this.ownerContext == context && this.refCount == 1);
  640. }
  641. internal void Clear()
  642. {
  643. this.count = 0;
  644. }
  645. internal void Reset(NodeSequence nextSeq)
  646. {
  647. this.count = 0;
  648. this.refCount = 0;
  649. this.next = nextSeq;
  650. }
  651. internal bool Compare(double val, RelationOperator op)
  652. {
  653. for (int i = 0; i < this.count; ++i)
  654. {
  655. if (this.items[i].Compare(val, op))
  656. {
  657. return true;
  658. }
  659. }
  660. return false;
  661. }
  662. internal bool Compare(string val, RelationOperator op)
  663. {
  664. Fx.Assert(null != val, "");
  665. for (int i = 0; i < this.count; ++i)
  666. {
  667. if (this.items[i].Compare(val, op))
  668. {
  669. return true;
  670. }
  671. }
  672. return false;
  673. }
  674. internal bool Compare(ref NodeSequenceItem item, RelationOperator op)
  675. {
  676. for (int i = 0; i < this.count; ++i)
  677. {
  678. if (this.items[i].Compare(ref item, op))
  679. {
  680. return true;
  681. }
  682. }
  683. return false;
  684. }
  685. internal bool Compare(NodeSequence sequence, RelationOperator op)
  686. {
  687. Fx.Assert(null != sequence, "");
  688. for (int i = 0; i < sequence.count; ++i)
  689. {
  690. if (this.Compare(ref sequence.items[i], op))
  691. {
  692. return true;
  693. }
  694. }
  695. return false;
  696. }
  697. #if NO
  698. void EnsureCapacity()
  699. {
  700. if (this.count == this.items.Length)
  701. {
  702. this.Grow(this.items.Length * 2);
  703. }
  704. }
  705. void EnsureCapacity(int capacity)
  706. {
  707. if (capacity > this.items.Length)
  708. {
  709. int newSize = this.items.Length * 2;
  710. this.Grow(newSize > capacity ? newSize : capacity);
  711. }
  712. }
  713. #endif
  714. internal bool Equals(string val)
  715. {
  716. Fx.Assert(null != val, "");
  717. for (int i = 0; i < this.count; ++i)
  718. {
  719. if (this.items[i].Equals(val))
  720. {
  721. return true;
  722. }
  723. }
  724. return false;
  725. }
  726. internal bool Equals(double val)
  727. {
  728. for (int i = 0; i < this.count; ++i)
  729. {
  730. if (this.items[i].Equals(val))
  731. {
  732. return true;
  733. }
  734. }
  735. return false;
  736. }
  737. internal static int GetContextSize(NodeSequence sequence, int itemIndex)
  738. {
  739. Fx.Assert(null != sequence, "");
  740. int size = sequence.items[itemIndex].Size;
  741. if (size <= 0)
  742. {
  743. return sequence.items[-size].Size;
  744. }
  745. return size;
  746. }
  747. void Grow(int newSize)
  748. {
  749. NodeSequenceItem[] newItems = new NodeSequenceItem[newSize];
  750. if (this.items != null)
  751. {
  752. Array.Copy(this.items, newItems, this.items.Length);
  753. }
  754. this.items = newItems;
  755. }
  756. /// <summary>
  757. /// Merge all nodesets in this sequence... turning it into a sequence with a single nodeset
  758. /// This is done by simply renumbering all positions.. and clearing the nodeset flag
  759. /// </summary>
  760. internal void Merge()
  761. {
  762. Merge(true);
  763. }
  764. internal void Merge(bool renumber)
  765. {
  766. if (this.count == 0)
  767. {
  768. return;
  769. }
  770. if (renumber)
  771. {
  772. RenumberItems();
  773. }
  774. }
  775. #if NO
  776. // Assumes list is flat and sorted
  777. internal void RemoveDuplicates()
  778. {
  779. if(this.count < 2)
  780. {
  781. return;
  782. }
  783. int last = 0;
  784. for(int next = 1; next < this.count; ++next)
  785. {
  786. if(Comparer.Compare(this.items[last], this.items[next]) != 0)
  787. {
  788. ++last;
  789. if(last != next)
  790. {
  791. this.items[last] = this.items[next];
  792. }
  793. }
  794. }
  795. this.count = last + 1;
  796. RenumberItems();
  797. }
  798. #endif
  799. void RenumberItems()
  800. {
  801. if (this.count > 0)
  802. {
  803. for (int i = 0; i < this.count; ++i)
  804. {
  805. this.items[i].SetPositionAndSize(i + 1, this.count);
  806. }
  807. this.items[this.count - 1].Flags |= NodeSequenceItemFlags.NodesetLast;
  808. }
  809. }
  810. #if NO
  811. internal void SortNodes()
  812. {
  813. this.Merge(false);
  814. // PERF, [....], make this work
  815. //Array.Sort<NodeSequenceItem>(this.items, 0, this.count, NodeSequence.Comparer);
  816. Array.Sort(this.items, 0, this.count, NodeSequence.ObjectComparer);
  817. RenumberItems();
  818. }
  819. #endif
  820. internal void StartNodeset()
  821. {
  822. this.position = 0;
  823. this.sizePosition = -this.count;
  824. }
  825. internal void StopNodeset()
  826. {
  827. switch (this.position)
  828. {
  829. default:
  830. int sizePos = -this.sizePosition;
  831. this.items[sizePos].Size = this.position;
  832. this.items[sizePos + this.position - 1].Last = true;
  833. break;
  834. case 0:
  835. break;
  836. case 1:
  837. this.items[-this.sizePosition].SetSizeAndLast();
  838. break;
  839. }
  840. }
  841. internal string StringValue()
  842. {
  843. if (this.count > 0)
  844. {
  845. return this.items[0].StringValue();
  846. }
  847. return string.Empty;
  848. }
  849. /// <summary>
  850. /// Union algorithm:
  851. /// 1. Add both sequences of items to a newly created sequence
  852. /// 2. Sort the items based on document position
  853. /// 3. Renumber positions in this new unionized sequence
  854. /// </summary>
  855. internal NodeSequence Union(ProcessingContext context, NodeSequence otherSeq)
  856. {
  857. NodeSequence seq = context.CreateSequence();
  858. SortedBuffer<QueryNode, QueryNodeComparer> buff = new SortedBuffer<QueryNode, QueryNodeComparer>(staticQueryNodeComparerInstance);
  859. for (int i = 0; i < this.count; ++i)
  860. buff.Add(this.items[i].Node);
  861. for (int i = 0; i < otherSeq.count; ++i)
  862. buff.Add(otherSeq.items[i].Node);
  863. for (int i = 0; i < buff.Count; ++i)
  864. seq.Add(buff[i]);
  865. seq.RenumberItems();
  866. return seq;
  867. /*
  868. // PERF, [....], I think we can do the merge ourselves and avoid the sort.
  869. // Need to verify that the sequences are always in document order.
  870. for(int i = 0; i < this.count; ++i)
  871. {
  872. seq.AddCopy(ref this.items[i]);
  873. }
  874. for(int i = 0; i < otherSeq.count; ++i)
  875. {
  876. seq.AddCopy(ref otherSeq.items[i]);
  877. }
  878. seq.SortNodes();
  879. seq.RemoveDuplicates();
  880. return seq;
  881. */
  882. }
  883. #region IQueryBufferPool Members
  884. #if NO
  885. public void Reset()
  886. {
  887. this.count = 0;
  888. this.Trim();
  889. }
  890. public void Trim()
  891. {
  892. if (this.count == 0)
  893. {
  894. this.items = null;
  895. }
  896. else if (this.count < this.items.Length)
  897. {
  898. NodeSequenceItem[] newItems = new NodeSequenceItem[this.count];
  899. Array.Copy(this.items, newItems, this.count);
  900. this.items = newItems;
  901. }
  902. }
  903. #endif
  904. #endregion
  905. }
  906. internal class NodeSequenceIterator : XPathNodeIterator
  907. {
  908. // Shared
  909. NodeSequence seq;
  910. // Instance
  911. NodeSequenceIterator data;
  912. int index;
  913. SeekableXPathNavigator nav; // the navigator that will be used by this iterator
  914. internal NodeSequenceIterator(NodeSequence seq)
  915. : base()
  916. {
  917. this.data = this;
  918. this.seq = seq;
  919. }
  920. internal NodeSequenceIterator(NodeSequenceIterator iter)
  921. {
  922. this.data = iter.data;
  923. this.index = iter.index;
  924. }
  925. public override int Count
  926. {
  927. get
  928. {
  929. return this.data.seq.Count;
  930. }
  931. }
  932. public override XPathNavigator Current
  933. {
  934. get
  935. {
  936. if (this.index == 0)
  937. {
  938. #pragma warning suppress 56503 // [....], postponing the public change
  939. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryProcessingException(QueryProcessingError.Unexpected, SR.GetString(SR.QueryContextNotSupportedInSequences)));
  940. }
  941. if (this.index > this.data.seq.Count)
  942. {
  943. #pragma warning suppress 56503 // [....], postponing the public change
  944. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.QueryAfterNodes)));
  945. }
  946. //
  947. // From MSDN - the public contract of .Current
  948. // You can use the properties of the XPathNavigator to return information on the current node.
  949. // However, the XPathNavigator cannot be used to move away from the selected node set.
  950. // Doing so could invalidate the state of the navigator. Alternatively, you can clone the XPathNavigator.
  951. // The cloned XPathNavigator can then be moved away from the selected node set. This is an application level decision.
  952. // Providing this functionality may effect the performance of the XPath query.
  953. //
  954. // Return the navigator as is - where it is positioned. If the user moved the navigator, then the user is
  955. // hosed. We will make no guarantees - and are not required to. Doing so would force cloning, which is expensive.
  956. //
  957. // NOTE: .Current can get called repeatedly, so its activity should be relative CHEAP.
  958. // No cloning, copying etc. All that work should be done in MoveNext()
  959. return this.nav;
  960. }
  961. }
  962. public override int CurrentPosition
  963. {
  964. get
  965. {
  966. return this.index;
  967. }
  968. }
  969. internal void Clear()
  970. {
  971. this.data.seq = null;
  972. this.nav = null;
  973. }
  974. public override XPathNodeIterator Clone()
  975. {
  976. return new NodeSequenceIterator(this);
  977. }
  978. public override IEnumerator GetEnumerator()
  979. {
  980. return new NodeSequenceEnumerator(this);
  981. }
  982. public override bool MoveNext()
  983. {
  984. if (null == this.data.seq)
  985. {
  986. // User is trying to use an iterator that is out of scope.
  987. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.QueryIteratorOutOfScope)));
  988. }
  989. if (this.index < this.data.seq.Count)
  990. {
  991. if (null == this.nav)
  992. {
  993. // We haven't aquired the navigator we will use for this iterator yet.
  994. this.nav = (SeekableXPathNavigator)this.data.seq[this.index].GetNavigator().Clone();
  995. }
  996. else
  997. {
  998. this.nav.CurrentPosition = this.data.seq[this.index].GetNavigatorPosition();
  999. }
  1000. this.index++;
  1001. return true;
  1002. }
  1003. this.index++;
  1004. this.nav = null;
  1005. return false;
  1006. }
  1007. public void Reset()
  1008. {
  1009. this.nav = null;
  1010. this.index = 0;
  1011. }
  1012. }
  1013. internal class NodeSequenceEnumerator : IEnumerator
  1014. {
  1015. NodeSequenceIterator iter;
  1016. internal NodeSequenceEnumerator(NodeSequenceIterator iter)
  1017. {
  1018. this.iter = new NodeSequenceIterator(iter);
  1019. Reset();
  1020. }
  1021. public object Current
  1022. {
  1023. get
  1024. {
  1025. if (this.iter.CurrentPosition == 0)
  1026. {
  1027. #pragma warning suppress 56503 // [....], postponing the public change
  1028. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.QueryBeforeNodes)));
  1029. }
  1030. if (this.iter.CurrentPosition > this.iter.Count)
  1031. {
  1032. #pragma warning suppress 56503 // [....], postponing the public change
  1033. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.QueryAfterNodes)));
  1034. }
  1035. return this.iter.Current;
  1036. }
  1037. }
  1038. public bool MoveNext()
  1039. {
  1040. return iter.MoveNext();
  1041. }
  1042. public void Reset()
  1043. {
  1044. this.iter.Reset();
  1045. }
  1046. }
  1047. internal class SafeNodeSequenceIterator : NodeSequenceIterator, IDisposable
  1048. {
  1049. ProcessingContext context;
  1050. int disposed;
  1051. NodeSequence seq;
  1052. public SafeNodeSequenceIterator(NodeSequence seq, ProcessingContext context)
  1053. : base(seq)
  1054. {
  1055. this.context = context;
  1056. this.seq = seq;
  1057. Interlocked.Increment(ref this.seq.refCount);
  1058. this.context.Processor.AddRef();
  1059. }
  1060. public override XPathNodeIterator Clone()
  1061. {
  1062. return new SafeNodeSequenceIterator(this.seq, this.context);
  1063. }
  1064. public void Dispose()
  1065. {
  1066. if (Interlocked.CompareExchange(ref this.disposed, 1, 0) == 0)
  1067. {
  1068. QueryProcessor processor = this.context.Processor;
  1069. this.context.ReleaseSequence(this.seq);
  1070. this.context.Processor.Matcher.ReleaseProcessor(processor);
  1071. }
  1072. }
  1073. }
  1074. internal struct NodesetIterator
  1075. {
  1076. int index;
  1077. int indexStart;
  1078. NodeSequence sequence;
  1079. NodeSequenceItem[] items;
  1080. internal NodesetIterator(NodeSequence sequence)
  1081. {
  1082. Fx.Assert(null != sequence, "");
  1083. this.sequence = sequence;
  1084. this.items = sequence.Items;
  1085. this.index = -1;
  1086. this.indexStart = -1;
  1087. }
  1088. internal int Index
  1089. {
  1090. get
  1091. {
  1092. return this.index;
  1093. }
  1094. }
  1095. internal bool NextItem()
  1096. {
  1097. if (-1 == this.index)
  1098. {
  1099. this.index = this.indexStart;
  1100. return true;
  1101. }
  1102. if (this.items[this.index].Last)
  1103. {
  1104. return false;
  1105. }
  1106. this.index++;
  1107. return true;
  1108. }
  1109. internal bool NextNodeset()
  1110. {
  1111. this.indexStart = this.index + 1;
  1112. this.index = -1;
  1113. return (this.indexStart < this.sequence.Count);
  1114. }
  1115. }
  1116. internal struct NodeSequenceBuilder
  1117. {
  1118. ProcessingContext context;
  1119. NodeSequence sequence;
  1120. internal NodeSequenceBuilder(ProcessingContext context, NodeSequence sequence)
  1121. {
  1122. this.context = context;
  1123. this.sequence = sequence;
  1124. }
  1125. internal NodeSequenceBuilder(ProcessingContext context)
  1126. : this(context, null)
  1127. {
  1128. }
  1129. #if NO
  1130. internal NodeSequenceBuilder(NodeSequence sequence)
  1131. : this(sequence.OwnerContext, sequence)
  1132. {
  1133. }
  1134. #endif
  1135. internal NodeSequence Sequence
  1136. {
  1137. get
  1138. {
  1139. return (null != this.sequence) ? this.sequence : NodeSequence.Empty;
  1140. }
  1141. set
  1142. {
  1143. this.sequence = value;
  1144. }
  1145. }
  1146. internal void Add(ref NodeSequenceItem item)
  1147. {
  1148. if (null == this.sequence)
  1149. {
  1150. this.sequence = this.context.CreateSequence();
  1151. this.sequence.StartNodeset();
  1152. }
  1153. this.sequence.Add(ref item);
  1154. }
  1155. internal void EndNodeset()
  1156. {
  1157. if (null != this.sequence)
  1158. {
  1159. this.sequence.StopNodeset();
  1160. }
  1161. }
  1162. internal void StartNodeset()
  1163. {
  1164. if (null != this.sequence)
  1165. {
  1166. this.sequence.StartNodeset();
  1167. }
  1168. }
  1169. }
  1170. }