279 lines
5.2 KiB
C++
279 lines
5.2 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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(1)
|
|
{ }
|
|
|
|
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_
|