|
|
///////////////////////////////////////////////////////////////////////////////
//
// FILE
//
// Tokens.h
//
// SYNOPSIS
//
// This file defines the various boolean token classes.
//
// MODIFICATION HISTORY
//
// 02/04/1998 Original version.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _TOKENS_H_
#define _TOKENS_H_
#include <algorithm>
#include <nap.h>
#include <nocopy.h>
//////////
// An abstract token.
//////////
class Token : public ICondition, NonCopyable { public: Token() throw () : refCount(0) { }
virtual ~Token() throw () { }
//////////
// IUnknown implementation.
//////////
STDMETHOD_(ULONG, AddRef)() { return InterlockedIncrement(&refCount); }
STDMETHOD_(ULONG, Release)() { LONG l = InterlockedDecrement(&refCount); if (l == 0) { delete this; } return l; }
STDMETHOD(QueryInterface)(const IID& iid, void** ppv) { if (iid == __uuidof(IUnknown)) { *ppv = static_cast<IUnknown*>(this); } else if (iid == __uuidof(ICondition)) { *ppv = static_cast<ICondition*>(this); } else { return E_NOINTERFACE; }
InterlockedIncrement(&refCount);
return S_OK; }
protected: LONG refCount; };
//////////
// A Boolean constant.
//////////
template <VARIANT_BOOL Value> class ConstantCondition : public Token { public: STDMETHOD(IsTrue)(/*[in]*/ IRequest*, /*[out, retval]*/ VARIANT_BOOL *pVal) { *pVal = Value; return S_OK; } };
//////////
// A unary operator in the logic tree.
//////////
class UnaryOperator : public Token { public: UnaryOperator(ICondition* cond) : operand(cond) { if (operand) { operand->AddRef(); } else { _com_issue_error(E_POINTER); } }
~UnaryOperator() throw () { operand->Release(); }
protected: ICondition* operand; };
//////////
// A binary operator in the logic tree.
//////////
class BinaryOperator : public Token { public: BinaryOperator(ICondition* left, ICondition* right) : left_operand(left), right_operand(right) { if (left_operand && right_operand) { left_operand->AddRef(); right_operand->AddRef(); } else { _com_issue_error(E_POINTER); } }
~BinaryOperator() throw () { left_operand->Release(); right_operand->Release(); }
protected: ICondition *left_operand, *right_operand; };
//////////
// AND Operator
//////////
class AndOperator : public BinaryOperator { public: AndOperator(ICondition* left, ICondition* right) : BinaryOperator(left, right) { }
STDMETHOD(IsTrue)(/*[in]*/ IRequest* pRequest, /*[out, retval]*/ VARIANT_BOOL *pVal) { HRESULT hr = left_operand->IsTrue(pRequest, pVal);
if (SUCCEEDED(hr) && *pVal != VARIANT_FALSE) { hr = right_operand->IsTrue(pRequest, pVal);
if (*pVal == VARIANT_FALSE) { // We should have tried the right operand first, so let's swap
// them and maybe we'll get lucky next time.
std::swap(left_operand, right_operand); } }
return hr; } };
//////////
// OR Operator
//////////
class OrOperator : public BinaryOperator { public: OrOperator(ICondition* left, ICondition* right) : BinaryOperator(left, right) { }
STDMETHOD(IsTrue)(/*[in]*/ IRequest* pRequest, /*[out, retval]*/ VARIANT_BOOL *pVal) { HRESULT hr = left_operand->IsTrue(pRequest, pVal);
if (SUCCEEDED(hr) && *pVal == VARIANT_FALSE) { hr = right_operand->IsTrue(pRequest, pVal);
if (*pVal != VARIANT_FALSE) { // We should have tried the right operand first, so let's swap
// them and maybe we'll get lucky next time.
std::swap(left_operand, right_operand); } }
return hr; } };
//////////
// XOR Operator
//////////
class XorOperator : public BinaryOperator { public: XorOperator(ICondition* left, ICondition* right) : BinaryOperator(left, right) { }
STDMETHOD(IsTrue)(/*[in]*/ IRequest* pRequest, /*[out, retval]*/ VARIANT_BOOL *pVal) { HRESULT hr = left_operand->IsTrue(pRequest, pVal);
if (SUCCEEDED(hr)) { BOOL b1 = (*pVal != VARIANT_FALSE);
hr = right_operand->IsTrue(pRequest, pVal);
if (SUCCEEDED(hr)) { BOOL b2 = (*pVal != VARIANT_FALSE);
*pVal = ((b1 && !b2) || (!b1 && b2)) ? VARIANT_TRUE : VARIANT_FALSE; } }
return hr; } };
//////////
// NOT Operator
//////////
class NotOperator : public UnaryOperator { public: NotOperator(ICondition* cond) : UnaryOperator(cond) { }
STDMETHOD(IsTrue)(/*[in]*/ IRequest* pRequest, /*[out, retval]*/ VARIANT_BOOL *pVal) { HRESULT hr = operand->IsTrue(pRequest, pVal);
if (SUCCEEDED(hr)) { *pVal = (*pVal != VARIANT_FALSE) ? VARIANT_FALSE : VARIANT_TRUE; }
return hr; } };
#endif //_TOKENS_H_
|