| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Dispatcher
- {
- using System.Collections;
- using System.Collections.Generic;
- using System.Runtime;
- // Based on the Paper: The IBS Tree: A Datastructure for finding all intervals that overlap a point.
- // by Eric Hanson & Moez Chaabouni, Nov, 1994
- internal enum IntervalOp : byte
- {
- LessThan,
- LessThanEquals
- }
- internal class Interval
- {
- QueryBranch branch;
- double lowerBound;
- IntervalOp lowerOp;
- double upperBound;
- IntervalOp upperOp;
- // Converts expressions of the form:
- // x < 5 => -infinity <= x and x < 5
- // x <= 5 => -infinity <= x and x <= 5
- // x > 5 => 5 < x <= infinity
- // x >= 5 => 5 <= x <= infinity
- //
- // The variable is always to the left
- internal Interval(double literal, RelationOperator op)
- {
- this.lowerBound = double.MinValue;
- this.upperBound = double.MaxValue;
- this.lowerOp = IntervalOp.LessThanEquals;
- this.upperOp = IntervalOp.LessThanEquals;
- Fx.Assert(RelationOperator.Eq != op && RelationOperator.Ne != op, "");
- switch (op)
- {
- case RelationOperator.Lt:
- this.upperBound = literal;
- this.upperOp = IntervalOp.LessThan;
- break;
- case RelationOperator.Le:
- this.upperBound = literal;
- break;
- case RelationOperator.Gt:
- this.lowerBound = literal;
- this.lowerOp = IntervalOp.LessThan;
- break;
- case RelationOperator.Ge:
- this.lowerBound = literal;
- break;
- }
- }
- #if NO
- internal Interval(double lowerBound, IntervalOp lowerOp, double upperBound, IntervalOp upperOp)
- {
- Fx.Assert(lowerBound <= upperBound, "");
- this.lowerBound = lowerBound;
- this.upperBound = upperBound;
- if (this.lowerBound == this.upperBound)
- {
- this.lowerOp = IntervalOp.LessThanEquals;
- this.upperOp = IntervalOp.LessThanEquals;
- }
- else
- {
- this.lowerOp = lowerOp;
- this.upperOp = upperOp;
- }
- }
- #endif
- internal QueryBranch Branch
- {
- get
- {
- return this.branch;
- }
- set
- {
- this.branch = value;
- }
- }
- internal double LowerBound
- {
- get
- {
- return this.lowerBound;
- }
- }
- internal IntervalOp LowerOp
- {
- get
- {
- return this.lowerOp;
- }
- }
- internal double UpperBound
- {
- get
- {
- return this.upperBound;
- }
- }
- internal IntervalOp UpperOp
- {
- get
- {
- return this.upperOp;
- }
- }
- #if NO
- internal bool Equals(Interval interval)
- {
- Fx.Assert(null != interval, "");
- return this.Equals(interval.lowerBound, interval.lowerOp, interval.upperBound, interval.upperOp);
- }
- #endif
- internal bool Equals(double lowerBound, IntervalOp lowerOp, double upperBound, IntervalOp upperOp)
- {
- return (this.lowerBound == lowerBound && this.lowerOp == lowerOp && this.upperBound == upperBound && this.upperOp == upperOp);
- }
- internal bool HasMatchingEndPoint(double endpoint)
- {
- return (this.lowerBound == endpoint || this.upperBound == endpoint);
- }
- }
- /// <summary>
- /// IntervalCollection
- /// All Contains/Find operations are currently linear, since they are required only during
- /// Inserts/Removes from the Interval Tree, which is not anticipated to be performance critical.
- /// </summary>
- internal class IntervalCollection : ArrayList
- {
- internal IntervalCollection()
- : base(1)
- {
- }
- internal bool HasIntervals
- {
- get
- {
- return (this.Count > 0);
- }
- }
- internal new Interval this[int index]
- {
- get
- {
- return (Interval)base[index];
- }
- }
- internal int Add(Interval interval)
- {
- Fx.Assert(null != interval, "");
- this.Capacity = this.Count + 1;
- return base.Add(interval);
- }
- internal int AddUnique(Interval interval)
- {
- Fx.Assert(null != interval, "");
- int index = this.IndexOf(interval);
- if (-1 == index)
- {
- return this.Add(interval);
- }
- return index;
- }
- internal IntervalCollection GetIntervalsWithEndPoint(double endPoint)
- {
- IntervalCollection matches = new IntervalCollection();
- int count = this.Count;
- for (int i = 0; i < count; ++i)
- {
- Interval interval = this[i];
- if (interval.HasMatchingEndPoint(endPoint))
- {
- matches.Add(interval);
- }
- }
- return matches;
- }
- internal int IndexOf(Interval interval)
- {
- Fx.Assert(null != interval, "");
- return base.IndexOf(interval);
- }
- internal int IndexOf(double endPoint)
- {
- int count = this.Count;
- for (int i = 0; i < count; ++i)
- {
- Interval interval = this[i];
- if (interval.HasMatchingEndPoint(endPoint))
- {
- return i;
- }
- }
- return -1;
- }
- internal int IndexOf(double lowerBound, IntervalOp lowerOp, double upperBound, IntervalOp upperOp)
- {
- int count = this.Count;
- for (int i = 0; i < count; ++i)
- {
- if (this[i].Equals(lowerBound, lowerOp, upperBound, upperOp))
- {
- return i;
- }
- }
- return -1;
- }
- internal void Remove(Interval interval)
- {
- Fx.Assert(null != interval, "");
- base.Remove(interval);
- this.TrimToSize();
- }
- internal void Trim()
- {
- this.TrimToSize();
- }
- }
- internal class IntervalBoundary
- {
- IntervalCollection eqSlot;
- IntervalCollection gtSlot;
- IntervalBoundary left;
- IntervalCollection ltSlot;
- IntervalBoundary parent;
- IntervalBoundary right;
- double val;
- internal IntervalBoundary(double val, IntervalBoundary parent)
- {
- this.val = val;
- this.parent = parent;
- }
- internal IntervalCollection EqSlot
- {
- get
- {
- return this.eqSlot;
- }
- }
- internal IntervalCollection GtSlot
- {
- get
- {
- return this.gtSlot;
- }
- }
- internal IntervalBoundary Left
- {
- get
- {
- return this.left;
- }
- set
- {
- this.left = value;
- }
- }
- internal IntervalCollection LtSlot
- {
- get
- {
- return this.ltSlot;
- }
- }
- internal IntervalBoundary Parent
- {
- get
- {
- return this.parent;
- }
- set
- {
- this.parent = value;
- }
- }
- internal IntervalBoundary Right
- {
- get
- {
- return this.right;
- }
- set
- {
- this.right = value;
- }
- }
- internal double Value
- {
- get
- {
- return this.val;
- }
- set
- {
- this.val = value;
- }
- }
- internal void AddToEqSlot(Interval interval)
- {
- Fx.Assert(null != interval, "");
- this.AddToSlot(ref this.eqSlot, interval);
- }
- internal void AddToGtSlot(Interval interval)
- {
- Fx.Assert(null != interval, "");
- this.AddToSlot(ref this.gtSlot, interval);
- }
- internal void AddToLtSlot(Interval interval)
- {
- Fx.Assert(null != interval, "");
- this.AddToSlot(ref this.ltSlot, interval);
- }
- void AddToSlot(ref IntervalCollection slot, Interval interval)
- {
- if (null == slot)
- {
- slot = new IntervalCollection();
- }
- slot.AddUnique(interval);
- }
- internal IntervalBoundary EnsureLeft(double val)
- {
- if (null == this.left)
- {
- this.left = new IntervalBoundary(val, this);
- }
- return this.left;
- }
- internal IntervalBoundary EnsureRight(double val)
- {
- if (null == this.right)
- {
- this.right = new IntervalBoundary(val, this);
- }
- return this.right;
- }
- #if NO
- internal Interval GetInterval(double lowerBound, IntervalOp lowerOp, double upperBound, IntervalOp upperOp)
- {
- Interval interval;
- if (
- null != (interval = this.GetIntervalFromSlot(this.eqSlot, lowerBound, lowerOp, upperBound, upperOp))
- || null != (interval = this.GetIntervalFromSlot(this.ltSlot, lowerBound, lowerOp, upperBound, upperOp))
- || null != (interval = this.GetIntervalFromSlot(this.gtSlot, lowerBound, lowerOp, upperBound, upperOp))
- )
- {
- return interval;
- }
- return null;
- }
- internal Interval GetIntervalByData(object data)
- {
- Interval interval;
- if (
- null != (interval = this.GetIntervalFromSlot(this.eqSlot, data))
- || null != (interval = this.GetIntervalFromSlot(this.ltSlot, data))
- || null != (interval = this.GetIntervalFromSlot(this.gtSlot, data))
- )
- {
- return interval;
- }
- return null;
- }
- Interval GetIntervalFromSlot(IntervalCollection slot, object data)
- {
- int index;
- if (null != slot && -1 != (index = slot.IndexOf(data)))
- {
- return slot[index];
- }
- return null;
- }
- Interval GetIntervalFromSlot(IntervalCollection slot, double lowerBound, IntervalOp lowerOp, double upperBound, IntervalOp upperOp)
- {
- int index;
- if (null != slot && -1 != (index = slot.IndexOf(lowerBound, lowerOp, upperBound, upperOp)))
- {
- return slot[index];
- }
- return null;
- }
- #endif
- internal void RemoveFromEqSlot(Interval interval)
- {
- Fx.Assert(null != interval, "");
- this.RemoveFromSlot(ref this.eqSlot, interval);
- }
- internal void RemoveFromGtSlot(Interval interval)
- {
- Fx.Assert(null != interval, "");
- this.RemoveFromSlot(ref this.gtSlot, interval);
- }
- internal void RemoveFromLtSlot(Interval interval)
- {
- Fx.Assert(null != interval, "");
- this.RemoveFromSlot(ref this.ltSlot, interval);
- }
- void RemoveFromSlot(ref IntervalCollection slot, Interval interval)
- {
- if (null != slot)
- {
- slot.Remove(interval);
- if (!slot.HasIntervals)
- {
- slot = null;
- }
- }
- }
- internal void Trim()
- {
- if (this.eqSlot != null)
- {
- this.eqSlot.Trim();
- }
- if (this.gtSlot != null)
- {
- this.gtSlot.Trim();
- }
- if (this.ltSlot != null)
- {
- this.ltSlot.Trim();
- }
- if (this.left != null)
- {
- this.left.Trim();
- }
- if (this.right != null)
- {
- this.right.Trim();
- }
- }
- }
- internal struct IntervalTreeTraverser
- {
- IntervalBoundary currentNode;
- IntervalBoundary nextNode;
- IntervalCollection slot;
- double val;
- internal IntervalTreeTraverser(double val, IntervalBoundary root)
- {
- Fx.Assert(null != root, "");
- this.currentNode = null;
- this.slot = null;
- this.nextNode = root;
- this.val = val;
- }
- internal IntervalCollection Slot
- {
- get
- {
- return this.slot;
- }
- }
- internal bool MoveNext()
- {
- while (null != this.nextNode)
- {
- this.currentNode = this.nextNode;
- double currentVal = this.currentNode.Value;
- if (val < currentVal)
- {
- this.slot = this.currentNode.LtSlot;
- this.nextNode = this.currentNode.Left;
- }
- else if (val > currentVal)
- {
- this.slot = this.currentNode.GtSlot;
- this.nextNode = this.currentNode.Right;
- }
- else
- {
- this.slot = this.currentNode.EqSlot;
- this.nextNode = null;
- }
- if (null != this.slot)
- {
- return true;
- }
- }
- return false;
- }
- }
- internal class IntervalTree
- {
- IntervalCollection intervals;
- IntervalBoundary root;
- internal IntervalTree()
- {
- }
- internal int Count
- {
- get
- {
- return (null != this.intervals) ? this.intervals.Count : 0;
- }
- }
- internal IntervalCollection Intervals
- {
- get
- {
- if (null == this.intervals)
- {
- return new IntervalCollection();
- }
- return this.intervals;
- }
- }
- #if NO
- internal bool IsEmpty
- {
- get
- {
- return (this.root == null);
- }
- }
- #endif
- internal IntervalBoundary Root
- {
- get
- {
- return this.root;
- }
- }
- internal void Add(Interval interval)
- {
- Fx.Assert(null != interval, "");
- this.AddIntervalToTree(interval);
- this.EnsureIntervals();
- this.intervals.Add(interval);
- }
- void AddIntervalToTree(Interval interval)
- {
- this.EditLeft(interval, true);
- this.EditRight(interval, true);
- }
- #if NO
- internal bool Contains(double lowerBound, IntervalOp lowerOp, double upperBound, IntervalOp upperOp)
- {
- if (null != this.intervals)
- {
- return (this.intervals.IndexOf(lowerBound, lowerOp, upperBound, upperOp) >= 0);
- }
- return false;
- }
- #endif
- void EditLeft(Interval interval, bool add)
- {
- if (add)
- {
- this.EnsureRoot(interval.LowerBound);
- }
- IntervalBoundary root = this.root;
- IntervalBoundary leftAncestor = null;
- while (true)
- {
- double rootVal = root.Value;
- if (rootVal < interval.LowerBound)
- {
- // root is outside the interval range because it is < the lower bound
- root = add ? root.EnsureRight(interval.LowerBound) : root.Right;
- continue;
- }
- // rootVal is >= to interval.lowerBound
- //
- // All values in thee subtree at 'root' are < leftAncestor.Value
- // All values to the left of this node cannot be in the interval because they are < the interval's
- // lower bound.
- // Values to the right of this node lie in range (root.Value to leftAncestor.Value)
- // Thus, the entire right subtree of root will be inside the range if the interval.upperBound
- // is >= leftAncestor.Value
- if (null != leftAncestor && leftAncestor.Value <= interval.UpperBound)
- {
- if (add)
- {
- root.AddToGtSlot(interval);
- }
- else
- {
- root.RemoveFromGtSlot(interval);
- }
- }
- if (rootVal > interval.LowerBound)
- { // This node itself lies in the range if it is also < the upper bound
- if (rootVal < interval.UpperBound)
- {
- if (add)
- {
- root.AddToEqSlot(interval);
- }
- else
- {
- root.RemoveFromEqSlot(interval);
- }
- }
- leftAncestor = root;
- root = add ? root.EnsureLeft(interval.LowerBound) : root.Left;
- continue;
- }
- // lowerBound == rootVal. We're done.
- if (IntervalOp.LessThanEquals == interval.LowerOp)
- {
- // If the range is inclusive of the lower bound (>=), then since this node == lowerBound,
- // it must be in the range.
- if (add)
- {
- root.AddToEqSlot(interval);
- }
- else
- {
- root.RemoveFromEqSlot(interval);
- }
- }
- break;
- }
- }
- void EditRight(Interval interval, bool add)
- {
- if (add)
- {
- this.EnsureRoot(interval.UpperBound);
- }
- IntervalBoundary root = this.root;
- IntervalBoundary rightAncestor = null;
- while (true)
- {
- double rootVal = root.Value;
- if (rootVal > interval.UpperBound)
- {
- // root is outside the interval range because it is > the upper bound
- root = add ? root.EnsureLeft(interval.UpperBound) : root.Left;
- continue;
- }
- // rootVal is <= to interval.UpperBound
- //
- // All values in the subtree at 'root' are > leftAncestor.Value
- // All values to the right of this node cannot be in the interval because they are > the interval's
- // upper bound.
- // Values to the left of this node lie in range (rightAncestor.Value to root.Value)
- // Thus, the entire left subtree of root will be inside the range if the interval.lowerBound
- // is <= rightAncestor.Value
- if (null != rightAncestor && rightAncestor.Value >= interval.LowerBound)
- {
- if (add)
- {
- root.AddToLtSlot(interval);
- }
- else
- {
- root.RemoveFromLtSlot(interval);
- }
- }
- if (rootVal < interval.UpperBound)
- {
- // This node itself lies in the range if it is also > the lower bound
- if (rootVal > interval.LowerBound)
- {
- if (add)
- {
- root.AddToEqSlot(interval);
- }
- else
- {
- root.RemoveFromEqSlot(interval);
- }
- }
- rightAncestor = root;
- root = add ? root.EnsureRight(interval.UpperBound) : root.Right;
- continue;
- }
- // upperBound == rootVal. We're done.
- // If upperBound == lowerBound, we already inserted this when doing AddLeft
- if (IntervalOp.LessThanEquals == interval.UpperOp)
- {
- // If the range is inclusive of the upper bound, then since this node == upperBound,
- // it must be in the range.
- if (add)
- {
- root.AddToEqSlot(interval);
- }
- else
- {
- root.RemoveFromEqSlot(interval);
- }
- }
- break;
- }
- }
- void EnsureIntervals()
- {
- if (null == this.intervals)
- {
- this.intervals = new IntervalCollection();
- }
- }
- void EnsureRoot(double val)
- {
- if (null == this.root)
- {
- this.root = new IntervalBoundary(val, null);
- }
- }
- internal IntervalBoundary FindBoundaryNode(double val)
- {
- return this.FindBoundaryNode(root, val);
- }
- internal IntervalBoundary FindBoundaryNode(IntervalBoundary root, double val)
- {
- IntervalBoundary boundary = null;
- if (null != root)
- {
- if (root.Value == val)
- {
- boundary = root;
- }
- else
- {
- if (null == (boundary = this.FindBoundaryNode(root.Left, val)))
- {
- boundary = this.FindBoundaryNode(root.Right, val);
- }
- }
- }
- return boundary;
- }
- internal Interval FindInterval(Interval interval)
- {
- return this.FindInterval(interval.LowerBound, interval.LowerOp, interval.UpperBound, interval.UpperOp);
- }
- internal Interval FindInterval(double lowerBound, IntervalOp lowerOp, double upperBound, IntervalOp upperOp)
- {
- if (null != this.intervals)
- {
- int index;
- if (-1 != (index = this.intervals.IndexOf(lowerBound, lowerOp, upperBound, upperOp)))
- {
- return this.intervals[index];
- }
- }
- return null;
- }
- /// <summary>
- /// An interval has been removed. Prune the tree appropriately
- /// </summary>
- /// <param name="intervalRemoved">interval that was removed</param>
- void PruneTree(Interval intervalRemoved)
- {
- // Delete endpoints if no other intervals have them
- int index;
- if (-1 == (index = this.intervals.IndexOf(intervalRemoved.LowerBound)))
- {
- this.RemoveBoundary(this.FindBoundaryNode(intervalRemoved.LowerBound));
- }
- if (intervalRemoved.LowerBound != intervalRemoved.UpperBound && -1 == (index = this.intervals.IndexOf(intervalRemoved.UpperBound)))
- {
- this.RemoveBoundary(this.FindBoundaryNode(intervalRemoved.UpperBound));
- }
- }
- internal void Remove(Interval interval)
- {
- Fx.Assert(null != interval, "");
- Fx.Assert(null != this.intervals, "");
- // First, delete all occurences of interval in the tree. Note: we do a reference equals
- this.RemoveIntervalFromTree(interval);
- // Remove interval from interval collection
- this.intervals.Remove(interval);
- // It may be possible to prune the tree.. this will do the necessary, if required
- this.PruneTree(interval);
- }
- void RemoveBoundary(IntervalBoundary boundary)
- {
- IntervalCollection replacementIntervals = null;
- int replacementCount = 0;
- if (null != boundary.Left && null != boundary.Right)
- {
- // Neither left/right are null. Typical binary tree node removal - replace the removed node
- // with the symmetric order predecessor
- IntervalBoundary replacement = boundary.Left;
- while (null != replacement.Right)
- {
- replacement = replacement.Right;
- }
- // Find all intervals with endpoint y in the tree
- replacementIntervals = this.intervals.GetIntervalsWithEndPoint(replacement.Value);
- // Remove the intervals from the tree
- replacementCount = replacementIntervals.Count;
- for (int i = 0; i < replacementCount; ++i)
- {
- this.RemoveIntervalFromTree(replacementIntervals[i]);
- }
- double val = boundary.Value;
- boundary.Value = replacement.Value;
- replacement.Value = val;
- boundary = replacement;
- }
- if (null != boundary.Left)
- {
- this.Replace(boundary, boundary.Left);
- }
- else
- {
- this.Replace(boundary, boundary.Right);
- }
- // Discard the node
- boundary.Parent = null;
- boundary.Left = null;
- boundary.Right = null;
- // Reinstall Intervals
- for (int i = 0; i < replacementCount; ++i)
- {
- this.AddIntervalToTree(replacementIntervals[i]);
- }
- }
- void RemoveIntervalFromTree(Interval interval)
- {
- this.EditLeft(interval, false);
- this.EditRight(interval, false);
- }
- void Replace(IntervalBoundary replace, IntervalBoundary with)
- {
- IntervalBoundary parent = replace.Parent;
- if (null != parent)
- {
- if (replace == parent.Left)
- {
- parent.Left = with;
- }
- else if (replace == parent.Right)
- {
- parent.Right = with;
- }
- }
- else
- {
- // Replacing root
- this.root = with;
- }
- if (null != with)
- {
- with.Parent = parent;
- }
- }
- internal void Trim()
- {
- this.intervals.Trim();
- this.root.Trim();
- }
- }
- internal class NumberRelationOpcode : LiteralRelationOpcode
- {
- double literal;
- RelationOperator op;
- internal NumberRelationOpcode(double literal, RelationOperator op)
- : this(OpcodeID.NumberRelation, literal, op)
- {
- }
- protected NumberRelationOpcode(OpcodeID id, double literal, RelationOperator op)
- : base(id)
- {
- this.literal = literal;
- this.op = op;
- }
- #if NO
- internal override ValueDataType DataType
- {
- get
- {
- return ValueDataType.Double;
- }
- }
- #endif
- internal override object Literal
- {
- get
- {
- return this.literal;
- }
- }
- #if NO
- internal RelationOperator Op
- {
- get
- {
- return this.op;
- }
- }
- #endif
- internal override bool Equals(Opcode opcode)
- {
- if (base.Equals(opcode))
- {
- NumberRelationOpcode numOp = (NumberRelationOpcode)opcode;
- return (numOp.op == this.op && numOp.literal == this.literal);
- }
- return false;
- }
- internal override Opcode Eval(ProcessingContext context)
- {
- Value[] values = context.Values;
- StackFrame arg = context.TopArg;
- for (int i = arg.basePtr; i <= arg.endPtr; ++i)
- {
- values[i].Update(context, values[i].CompareTo(this.literal, op));
- }
- return this.next;
- }
- internal Interval ToInterval()
- {
- return new Interval(this.literal, this.op);
- }
- }
- internal class NumberIntervalOpcode : NumberRelationOpcode
- {
- Interval interval;
- internal NumberIntervalOpcode(double literal, RelationOperator op)
- : base(OpcodeID.NumberInterval, literal, op)
- {
- }
- internal override object Literal
- {
- get
- {
- if (null == this.interval)
- {
- this.interval = this.ToInterval();
- }
- return this.interval;
- }
- }
- internal override void Add(Opcode op)
- {
- NumberIntervalOpcode intervalOp = op as NumberIntervalOpcode;
- if (null == intervalOp)
- {
- base.Add(op);
- return;
- }
- Fx.Assert(null != this.prev, "");
- NumberIntervalBranchOpcode branch = new NumberIntervalBranchOpcode();
- this.prev.Replace(this, branch);
- branch.Add(this);
- branch.Add(intervalOp);
- }
- }
- internal class IntervalBranchIndex : QueryBranchIndex
- {
- IntervalTree intervalTree;
- internal IntervalBranchIndex()
- {
- this.intervalTree = new IntervalTree();
- }
- internal override int Count
- {
- get
- {
- return this.intervalTree.Count;
- }
- }
- internal override QueryBranch this[object key]
- {
- get
- {
- Interval interval = this.intervalTree.FindInterval((Interval)key);
- if (null != interval)
- {
- return interval.Branch;
- }
- return null;
- }
- set
- {
- Interval interval = (Interval)key;
- interval.Branch = value;
- this.intervalTree.Add(interval);
- }
- }
- internal override void CollectXPathFilters(ICollection<MessageFilter> filters)
- {
- for (int i = 0; i < this.intervalTree.Intervals.Count; ++i)
- {
- this.intervalTree.Intervals[i].Branch.Branch.CollectXPathFilters(filters);
- }
- }
- #if NO
- internal override IEnumerator GetEnumerator()
- {
- return this.intervalTree.Intervals.GetEnumerator();
- }
-
- #endif
- void Match(int valIndex, double point, QueryBranchResultSet results)
- {
- IntervalTreeTraverser traverser = new IntervalTreeTraverser(point, this.intervalTree.Root);
- while (traverser.MoveNext())
- {
- IntervalCollection matches = traverser.Slot;
- for (int i = 0, count = matches.Count; i < count; ++i)
- {
- QueryBranch branch = matches[i].Branch;
- if (null != branch)
- {
- results.Add(branch, valIndex);
- }
- }
- }
- }
- internal override void Match(int valIndex, ref Value val, QueryBranchResultSet results)
- {
- if (ValueDataType.Sequence == val.Type)
- {
- NodeSequence sequence = val.Sequence;
- for (int i = 0; i < sequence.Count; ++i)
- {
- this.Match(valIndex, sequence.Items[i].NumberValue(), results);
- }
- }
- else
- {
- this.Match(valIndex, val.ToDouble(), results);
- }
- }
- internal override void Remove(object key)
- {
- this.intervalTree.Remove((Interval)key);
- }
- internal override void Trim()
- {
- this.intervalTree.Trim();
- }
- }
- internal class NumberIntervalBranchOpcode : QueryConditionalBranchOpcode
- {
- internal NumberIntervalBranchOpcode()
- : base(OpcodeID.NumberIntervalBranch, new IntervalBranchIndex())
- {
- }
- internal override LiteralRelationOpcode ValidateOpcode(Opcode opcode)
- {
- NumberIntervalOpcode numOp = opcode as NumberIntervalOpcode;
- if (null != numOp)
- {
- return numOp;
- }
- return null;
- }
- }
- }
|