/////////////////////////////////////////////////////////////////////////////// // // 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 #include #include ////////// // 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(this); } else if (iid == __uuidof(ICondition)) { *ppv = static_cast(this); } else { return E_NOINTERFACE; } InterlockedIncrement(&refCount); return S_OK; } protected: LONG refCount; }; ////////// // A Boolean constant. ////////// template 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_