| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Dispatcher
- {
- using System.Runtime;
- enum ValueDataType : byte
- {
- None = 0,
- Boolean,
- Double,
- StackFrame,
- Sequence,
- String
- }
- // Value is like Variant. Since a Value is only temporary storage, we use memory to avoid typecasting type
- // casting, which in C# is expensive. Value contains storage for every possible XPath data type.
- // We avoid data copying by being smart about how we pass Value around - values are either accessed via
- // method calls, or the value object itself is passed by ref
- //
- // The filter engine never deals with a single value per se. We only work with Sets of Values. A single value
- // is a ValueSet of size 1
- //
- internal struct Value
- {
- bool boolVal;
- double dblVal;
- StackFrame frame;
- NodeSequence sequence;
- string strVal;
- ValueDataType type;
- internal bool Boolean
- {
- get
- {
- return this.boolVal;
- }
- set
- {
- this.type = ValueDataType.Boolean;
- this.boolVal = value;
- }
- }
- internal double Double
- {
- get
- {
- return this.dblVal;
- }
- set
- {
- this.type = ValueDataType.Double;
- this.dblVal = value;
- }
- }
- internal StackFrame Frame
- {
- get
- {
- return this.frame;
- }
- #if NO
- set
- {
- this.type = ValueDataType.StackFrame;
- this.frame = value;
- }
- #endif
- }
- #if NO
- internal int FrameCount
- {
- get
- {
- return this.frame.Count;
- }
- }
- #endif
- internal int FrameEndPtr
- {
- #if NO
- get
- {
- return this.frame.endPtr;
- }
- #endif
- set
- {
- Fx.Assert(this.IsType(ValueDataType.StackFrame), "");
- this.frame.EndPtr = value;
- }
- }
- #if NO
- internal int FrameBasePtr
- {
- get
- {
- return this.frame.basePtr;
- }
- }
-
- internal int StackPtr
- {
- get
- {
- return this.frame.basePtr - 1;
- }
- }
- #endif
- internal int NodeCount
- {
- get
- {
- return this.sequence.Count;
- }
- }
- internal NodeSequence Sequence
- {
- get
- {
- return this.sequence;
- }
- set
- {
- this.type = ValueDataType.Sequence;
- this.sequence = value;
- }
- }
- internal string String
- {
- get
- {
- return this.strVal;
- }
- set
- {
- this.type = ValueDataType.String;
- this.strVal = value;
- }
- }
- internal ValueDataType Type
- {
- get
- {
- return this.type;
- }
- }
- internal void Add(double val)
- {
- Fx.Assert(ValueDataType.Double == this.type, "");
- this.dblVal += val;
- }
- #if NO
- internal void Clear()
- {
- this.type = ValueDataType.None;
- this.sequence = null;
- }
- #endif
- internal void Clear(ProcessingContext context)
- {
- if (ValueDataType.Sequence == this.type)
- {
- this.ReleaseSequence(context);
- }
- this.type = ValueDataType.None;
- }
- // Fully general compare
- internal bool CompareTo(ref Value val, RelationOperator op)
- {
- switch (this.type)
- {
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
- case ValueDataType.Boolean:
- switch (val.type)
- {
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
- case ValueDataType.Boolean:
- return QueryValueModel.Compare(this.boolVal, val.boolVal, op);
- case ValueDataType.Double:
- return QueryValueModel.Compare(this.boolVal, val.dblVal, op);
- case ValueDataType.Sequence:
- return QueryValueModel.Compare(this.boolVal, val.sequence, op);
- case ValueDataType.String:
- return QueryValueModel.Compare(this.boolVal, val.strVal, op);
- }
- case ValueDataType.Double:
- switch (val.type)
- {
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
- case ValueDataType.Boolean:
- return QueryValueModel.Compare(this.dblVal, val.boolVal, op);
- case ValueDataType.Double:
- return QueryValueModel.Compare(this.dblVal, val.dblVal, op);
- case ValueDataType.Sequence:
- return QueryValueModel.Compare(this.dblVal, val.sequence, op);
- case ValueDataType.String:
- return QueryValueModel.Compare(this.dblVal, val.strVal, op);
- }
- case ValueDataType.Sequence:
- switch (val.type)
- {
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
- case ValueDataType.Boolean:
- return QueryValueModel.Compare(this.sequence, val.boolVal, op);
- case ValueDataType.Double:
- return QueryValueModel.Compare(this.sequence, val.dblVal, op);
- case ValueDataType.Sequence:
- return QueryValueModel.Compare(this.sequence, val.sequence, op);
- case ValueDataType.String:
- return QueryValueModel.Compare(this.sequence, val.strVal, op);
- }
- case ValueDataType.String:
- switch (val.type)
- {
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
- case ValueDataType.Boolean:
- return QueryValueModel.Compare(this.strVal, val.boolVal, op);
- case ValueDataType.Double:
- return QueryValueModel.Compare(this.strVal, val.dblVal, op);
- case ValueDataType.Sequence:
- return QueryValueModel.Compare(this.strVal, val.sequence, op);
- case ValueDataType.String:
- return QueryValueModel.Compare(this.strVal, val.strVal, op);
- }
- }
- }
- internal bool CompareTo(double val, RelationOperator op)
- {
- switch (this.type)
- {
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
- case ValueDataType.Boolean:
- return QueryValueModel.Compare(this.boolVal, val, op);
- case ValueDataType.Double:
- return QueryValueModel.Compare(this.dblVal, val, op);
- case ValueDataType.Sequence:
- return QueryValueModel.Compare(this.sequence, val, op);
- case ValueDataType.String:
- return QueryValueModel.Compare(this.strVal, val, op);
- }
- }
- internal void ConvertTo(ProcessingContext context, ValueDataType newType)
- {
- Fx.Assert(null != context, "");
- if (newType == this.type)
- {
- return;
- }
- switch (newType)
- {
- default:
- break;
- case ValueDataType.Boolean:
- this.boolVal = this.ToBoolean();
- break;
- case ValueDataType.Double:
- this.dblVal = this.ToDouble();
- break;
- case ValueDataType.String:
- this.strVal = this.ToString();
- break;
- }
- if (ValueDataType.Sequence == this.type)
- {
- this.ReleaseSequence(context);
- }
- this.type = newType;
- }
- internal bool Equals(string val)
- {
- switch (this.type)
- {
- default:
- Fx.Assert("Invalid Type");
- return false;
- case ValueDataType.Boolean:
- return QueryValueModel.Equals(this.boolVal, val);
- case ValueDataType.Double:
- return QueryValueModel.Equals(this.dblVal, val);
- case ValueDataType.Sequence:
- return QueryValueModel.Equals(this.sequence, val);
- case ValueDataType.String:
- return QueryValueModel.Equals(this.strVal, val);
- }
- }
- internal bool Equals(double val)
- {
- switch (this.type)
- {
- default:
- Fx.Assert("Invalid Type");
- return false;
- case ValueDataType.Boolean:
- return QueryValueModel.Equals(this.boolVal, val);
- case ValueDataType.Double:
- return QueryValueModel.Equals(this.dblVal, val);
- case ValueDataType.Sequence:
- return QueryValueModel.Equals(this.sequence, val);
- case ValueDataType.String:
- return QueryValueModel.Equals(val, this.strVal);
- }
- }
- #if NO
- internal bool Equals(bool val)
- {
- switch (this.type)
- {
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new QueryProcessingException(QueryProcessingError.TypeMismatch), TraceEventType.Critical);
- case ValueDataType.Boolean:
- return QueryValueModel.Equals(this.boolVal, val);
- case ValueDataType.Double:
- return QueryValueModel.Equals(this.dblVal, val);
- case ValueDataType.Sequence:
- return QueryValueModel.Equals(this.sequence, val);
- case ValueDataType.String:
- return QueryValueModel.Equals(this.strVal, val);
- }
- }
- #endif
- internal bool GetBoolean()
- {
- if (ValueDataType.Boolean != this.type)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
- }
- return this.boolVal;
- }
- internal double GetDouble()
- {
- if (ValueDataType.Double != this.type)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
- }
- return this.dblVal;
- }
- internal NodeSequence GetSequence()
- {
- if (ValueDataType.Sequence != this.type)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
- }
- return this.sequence;
- }
- internal string GetString()
- {
- if (ValueDataType.String != this.type)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
- }
- return this.strVal;
- }
- internal bool IsType(ValueDataType type)
- {
- return (type == this.type);
- }
- internal void Multiply(double val)
- {
- Fx.Assert(ValueDataType.Double == this.type, "");
- this.dblVal *= val;
- }
- internal void Negate()
- {
- Fx.Assert(this.type == ValueDataType.Double, "");
- this.dblVal = -this.dblVal;
- }
- internal void Not()
- {
- Fx.Assert(this.type == ValueDataType.Boolean, "");
- this.boolVal = !this.boolVal;
- }
- internal void ReleaseSequence(ProcessingContext context)
- {
- Fx.Assert(null != context && this.type == ValueDataType.Sequence && null != this.sequence, "");
- context.ReleaseSequence(this.sequence);
- this.sequence = null;
- }
- internal void StartFrame(int start)
- {
- this.type = ValueDataType.StackFrame;
- this.frame.basePtr = start + 1;
- this.frame.endPtr = start;
- }
- #if NO
- internal void Subtract(double dblVal)
- {
- Fx.Assert(ValueDataType.Double == this.type, "");
- this.dblVal -= dblVal;
- }
- #endif
- internal bool ToBoolean()
- {
- switch (this.type)
- {
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
- case ValueDataType.Boolean:
- return this.boolVal;
- case ValueDataType.Double:
- return QueryValueModel.Boolean(this.dblVal);
- case ValueDataType.Sequence:
- return QueryValueModel.Boolean(this.sequence);
- case ValueDataType.String:
- return QueryValueModel.Boolean(this.strVal);
- }
- }
- internal double ToDouble()
- {
- switch (this.type)
- {
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
- case ValueDataType.Boolean:
- return QueryValueModel.Double(this.boolVal);
- case ValueDataType.Double:
- return this.dblVal;
- case ValueDataType.Sequence:
- return QueryValueModel.Double(this.sequence);
- case ValueDataType.String:
- return QueryValueModel.Double(this.strVal);
- }
- }
- public override string ToString()
- {
- switch (this.type)
- {
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperCritical(new QueryProcessingException(QueryProcessingError.TypeMismatch));
- case ValueDataType.Boolean:
- return QueryValueModel.String(this.boolVal);
- case ValueDataType.Double:
- return QueryValueModel.String(this.dblVal);
- case ValueDataType.Sequence:
- return QueryValueModel.String(this.sequence);
- case ValueDataType.String:
- return this.strVal;
- }
- }
- internal void Update(ProcessingContext context, bool val)
- {
- if (ValueDataType.Sequence == this.type)
- {
- context.ReleaseSequence(this.sequence);
- }
- this.Boolean = val;
- }
- internal void Update(ProcessingContext context, double val)
- {
- if (ValueDataType.Sequence == this.type)
- {
- context.ReleaseSequence(this.sequence);
- }
- this.Double = val;
- }
- internal void Update(ProcessingContext context, string val)
- {
- if (ValueDataType.Sequence == this.type)
- {
- context.ReleaseSequence(this.sequence);
- }
- this.String = val;
- }
- internal void Update(ProcessingContext context, NodeSequence val)
- {
- if (ValueDataType.Sequence == this.type)
- {
- context.ReleaseSequence(this.sequence);
- }
- this.Sequence = val;
- }
- }
- }
|