|
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel.Dispatcher
{
using System.Collections.Generic;
using System.Runtime;
internal enum RelationOperator
{
None,
Eq,
Ne,
Gt,
Ge,
Lt,
Le
}
/// <summary>
/// General relation opcode: compares any two values on the value stack
/// </summary>
internal class RelationOpcode : Opcode
{
protected RelationOperator op;
internal RelationOpcode(RelationOperator op)
: this(OpcodeID.Relation, op)
{
}
protected RelationOpcode(OpcodeID id, RelationOperator op)
: base(id)
{
this.op = op;
}
internal override bool Equals(Opcode op)
{
if (base.Equals(op))
{
return (this.op == ((RelationOpcode)op).op);
}
return false;
}
internal override Opcode Eval(ProcessingContext context)
{
StackFrame argX = context.TopArg;
StackFrame argY = context.SecondArg;
Fx.Assert(argX.Count == argY.Count, "");
Value[] values = context.Values;
while (argX.basePtr <= argX.endPtr)
{
values[argY.basePtr].Update(context, values[argY.basePtr].CompareTo(ref values[argX.basePtr], op));
argX.basePtr++;
argY.basePtr++;
}
context.PopFrame();
return this.next;
}
#if DEBUG_FILTER
public override string ToString()
{
return string.Format("{0} {1}", base.ToString(), this.op.ToString());
}
#endif
}
internal abstract class LiteralRelationOpcode : Opcode
{
internal LiteralRelationOpcode(OpcodeID id)
: base(id)
{
this.flags |= OpcodeFlags.Literal;
}
#if NO
internal abstract ValueDataType DataType
{
get;
}
#endif
internal abstract object Literal
{
get;
}
#if DEBUG_FILTER
public override string ToString()
{
return string.Format("{0} '{1}'", base.ToString(), this.Literal);
}
#endif
}
internal class StringEqualsOpcode : LiteralRelationOpcode
{
string literal;
internal StringEqualsOpcode(string literal)
: base(OpcodeID.StringEquals)
{
Fx.Assert(null != literal, "");
this.literal = literal;
}
#if NO
internal override ValueDataType DataType
{
get
{
return ValueDataType.String;
}
}
#endif
internal override object Literal
{
get
{
return this.literal;
}
}
internal override void Add(Opcode op)
{
StringEqualsOpcode strEqOp = op as StringEqualsOpcode;
if (null == strEqOp)
{
base.Add(op);
return;
}
Fx.Assert(null != this.prev, "");
StringEqualsBranchOpcode branch = new StringEqualsBranchOpcode();
this.prev.Replace(this, branch);
branch.Add(this);
branch.Add(strEqOp);
}
internal override bool Equals(Opcode op)
{
if (base.Equals(op))
{
StringEqualsOpcode strEqOp = (StringEqualsOpcode)op;
return (strEqOp.literal == this.literal);
}
return false;
}
internal override Opcode Eval(ProcessingContext context)
{
Value[] values = context.Values;
StackFrame arg = context.TopArg;
if (1 == arg.Count)
{
values[arg.basePtr].Update(context, values[arg.basePtr].Equals(this.literal));
}
else
{
for (int i = arg.basePtr; i <= arg.endPtr; ++i)
{
values[i].Update(context, values[i].Equals(this.literal));
}
}
return this.next;
}
}
internal class NumberEqualsOpcode : LiteralRelationOpcode
{
double literal;
internal NumberEqualsOpcode(double literal)
: base(OpcodeID.NumberEquals)
{
this.literal = literal;
}
#if NO
internal override ValueDataType DataType
{
get
{
return ValueDataType.Double;
}
}
#endif
internal override object Literal
{
get
{
return this.literal;
}
}
internal override void Add(Opcode op)
{
NumberEqualsOpcode numEqOp = op as NumberEqualsOpcode;
if (null == numEqOp)
{
base.Add(op);
return;
}
Fx.Assert(null != this.prev, "");
NumberEqualsBranchOpcode branch = new NumberEqualsBranchOpcode();
this.prev.Replace(this, branch);
branch.Add(this);
branch.Add(numEqOp);
}
internal override bool Equals(Opcode op)
{
if (base.Equals(op))
{
NumberEqualsOpcode numEqOp = (NumberEqualsOpcode)op;
return (numEqOp.literal == this.literal);
}
return false;
}
internal override Opcode Eval(ProcessingContext context)
{
Value[] values = context.Values;
StackFrame arg = context.TopArg;
if (1 == arg.Count)
{
values[arg.basePtr].Update(context, values[arg.basePtr].Equals(this.literal));
}
else
{
for (int i = arg.basePtr; i <= arg.endPtr; ++i)
{
values[i].Update(context, values[i].Equals(this.literal));
}
}
return this.next;
}
}
internal abstract class HashBranchIndex : QueryBranchIndex
{
Dictionary<object, QueryBranch> literals;
internal HashBranchIndex()
{
this.literals = new Dictionary<object, QueryBranch>();
}
internal override int Count
{
get
{
return this.literals.Count;
}
}
internal override QueryBranch this[object literal]
{
get
{
QueryBranch result;
if (this.literals.TryGetValue(literal, out result))
{
return result;
}
return null;
}
set
{
this.literals[literal] = value;
}
}
internal override void CollectXPathFilters(ICollection<MessageFilter> filters)
{
foreach (QueryBranch branch in this.literals.Values)
{
branch.Branch.CollectXPathFilters(filters);
}
}
#if NO
internal override IEnumerator GetEnumerator()
{
return this.literals.GetEnumerator();
}
#endif
internal override void Remove(object key)
{
this.literals.Remove(key);
}
internal override void Trim()
{
// Can't compact Hashtable
}
}
internal class StringBranchIndex : HashBranchIndex
{
internal override void Match(int valIndex, ref Value val, QueryBranchResultSet results)
{
QueryBranch branch = null;
if (ValueDataType.Sequence == val.Type)
{
NodeSequence sequence = val.Sequence;
for (int i = 0; i < sequence.Count; ++i)
{
branch = this[sequence.Items[i].StringValue()];
if (null != branch)
{
results.Add(branch, valIndex);
}
}
}
else
{
Fx.Assert(val.Type == ValueDataType.String, "");
branch = this[val.String];
if (null != branch)
{
results.Add(branch, valIndex);
}
}
}
}
internal class StringEqualsBranchOpcode : QueryConditionalBranchOpcode
{
internal StringEqualsBranchOpcode()
: base(OpcodeID.StringEqualsBranch, new StringBranchIndex())
{
}
internal override LiteralRelationOpcode ValidateOpcode(Opcode opcode)
{
StringEqualsOpcode numOp = opcode as StringEqualsOpcode;
if (null != numOp)
{
return numOp;
}
return null;
}
}
internal class NumberBranchIndex : HashBranchIndex
{
internal override void Match(int valIndex, ref Value val, QueryBranchResultSet results)
{
QueryBranch branch = null;
if (ValueDataType.Sequence == val.Type)
{
NodeSequence sequence = val.Sequence;
for (int i = 0; i < sequence.Count; ++i)
{
branch = this[sequence.Items[i].NumberValue()];
if (null != branch)
{
results.Add(branch, valIndex);
}
}
}
else
{
branch = this[val.ToDouble()];
if (null != branch)
{
results.Add(branch, valIndex);
}
}
}
}
internal class NumberEqualsBranchOpcode : QueryConditionalBranchOpcode
{
internal NumberEqualsBranchOpcode()
: base(OpcodeID.NumberEqualsBranch, new NumberBranchIndex())
{
}
internal override LiteralRelationOpcode ValidateOpcode(Opcode opcode)
{
NumberEqualsOpcode numOp = opcode as NumberEqualsOpcode;
if (null != numOp)
{
return numOp;
}
return null;
}
}
}
|