//------------------------------------------------------------
// 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
}
///
/// General relation opcode: compares any two values on the value stack
///
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