📄 asmrulep.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
// #include "hlxclib/stdio.h" /* printf */
#include "hxtypes.h" /* Basic Types */
#include "hlxclib/stdlib.h"
#include "hxstrutl.h"
#include "hxcom.h" /* IUnknown */
#include "ihxpckts.h"
#include "asmrulep.h" /* ASM Public Include File */
#include "asmrulpp.h" /* ASM Private Include File */
#include "chxpckts.h"
#define RULE_VAL_INFINITY -1
#include "hxheap.h"
/*
#ifdef _DEBUG
#undef HX_THIS_FILE
static const char HX_THIS_FILE[] = __FILE__;
#endif
*/
static const char* const zpOpName[] =
{
">",
"<",
">=",
"<=",
"==",
"!=",
"AND",
"OR"
};
ASMRuleExpression::ASMRuleExpression(const char* pExpression)
{
int temp;
char* pTemp = new char[temp = (strlen(pExpression) + 1)];
memcpy(pTemp, pExpression, temp); /* Flawfinder: ignore */
m_ulNumThresholds = 1; // always have one zero rule
m_pHead = Parse(pTemp, m_ulNumThresholds);
delete[] pTemp;
}
ASMRuleExpression::~ASMRuleExpression()
{
RDelete(m_pHead);
}
/* Note: This parse is destructive to pExpression */
Node*
ASMRuleExpression::Parse(char* pExpression, UINT32& ulNumThreshold)
{
char* pTemp = pExpression;
int PLevel = 0;
BOOL bStripAgain = 1;
int OperSize;
//printf ("Parse Expression: %s\n", pExpression);
// Strip outside unneccesary parens
while ((*pExpression == '(') && (bStripAgain))
{
for (pTemp = pExpression, PLevel = 0; *pTemp; pTemp++)
{
if (*pTemp == '(')
PLevel++;
if (*pTemp == ')')
{
PLevel--;
if ((!(*(pTemp + 1))) && (!PLevel))
{
pExpression++;
pExpression[strlen(pExpression) - 1] = 0;
bStripAgain = 1;
break;
}
if (!PLevel)
{
bStripAgain = 0;
break;
}
}
}
}
for (pTemp = pExpression, PLevel = 0; *pTemp; pTemp++)
{
if (*pTemp == '(')
PLevel++;
if (*pTemp == ')')
PLevel--;
if (!PLevel)
{
OperSize = 1;
if (((*pTemp == '>') || (*pTemp == '<')) ||
((*pTemp == '=') || (*pTemp == '!')) ||
((*pTemp == '&') || (*pTemp == '|')))
{
OperatorNode* pNode = new OperatorNode;
pNode->m_Type = HX_RE_OPERATOR;
switch (*pTemp)
{
case '>':
if ((*(pTemp + 1)) == '=')
{
pNode->m_Data = HX_RE_GREATEREQUAL;
OperSize = 2;
}
else
pNode->m_Data = HX_RE_GREATER;
break;
case '<':
if ((*(pTemp + 1)) == '=')
{
pNode->m_Data = HX_RE_LESSEQUAL;
OperSize = 2;
}
else
pNode->m_Data = HX_RE_LESS;
break;
case '=':
if ((*(pTemp + 1)) == '=')
{
pNode->m_Data = HX_RE_EQUAL;
OperSize = 2;
}
break;
case '!':
if ((*(pTemp + 1)) == '=')
{
pNode->m_Data = HX_RE_NOTEQUAL;
OperSize = 2;
}
break;
case '&':
if ((*(pTemp + 1)) == '&')
{
pNode->m_Data = HX_RE_AND;
OperSize = 2;
}
break;
case '|':
if ((*(pTemp + 1)) == '|')
{
pNode->m_Data = HX_RE_OR;
OperSize = 2;
}
break;
default:
break;
};
*pTemp = 0;
pNode->m_pLeft = Parse(pExpression, ulNumThreshold);
pNode->m_pRight = Parse(pTemp + OperSize, ulNumThreshold);
return pNode;
}
}
}
for (pTemp = pExpression, PLevel = 0; *pTemp; pTemp++)
{
if (*pTemp == '(')
PLevel++;
if (*pTemp == ')')
PLevel--;
if (!PLevel)
{
if (*pTemp == '$')
{
VariableNode* pNode = new VariableNode;
pNode->m_Type = HX_RE_VARIABLE;
pNode->m_Data = new char[strlen(pTemp)];
memcpy(pNode->m_Data, pTemp + 1, strlen(pTemp)); /* Flawfinder: ignore */
pNode->m_pLeft = 0;
pNode->m_pRight = 0;
ulNumThreshold++; // each open variable means one more threshold.
return pNode;
}
}
}
for (pTemp = pExpression, PLevel = 0; *pTemp; pTemp++)
{
if (*pTemp == '(')
PLevel++;
if (*pTemp == ')')
PLevel--;
if (!PLevel)
{
if ((*pTemp == '0') || (*pTemp == '1') || (*pTemp == '2') ||
(*pTemp == '3') || (*pTemp == '4') || (*pTemp == '5') ||
(*pTemp == '6') || (*pTemp == '7') || (*pTemp == '8') ||
(*pTemp == '9'))
{
if (strchr(pTemp, '.'))
{
FloatNode* pNode = new FloatNode;
pNode->m_Type = HX_RE_FLOAT;
pNode->m_Data = (float)atof(pTemp);
pNode->m_pLeft = 0;
pNode->m_pRight = 0;
return pNode;
}
else
{
IntegerNode* pNode = new IntegerNode;
pNode->m_Type = HX_RE_INTEGER;
pNode->m_Data = atoi(pTemp);
pNode->m_pLeft = 0;
pNode->m_pRight = 0;
return pNode;
}
}
}
}
//printf ("Panic: Bad rule\n");
return 0;
}
void
ASMRuleExpression::Dump()
{
//printf ("Dumping ASMRuleExpression:\n");
RDump(m_pHead);
//printf ("\n");
}
void
ASMRuleExpression::RDump(Node* pNode)
{
if (!pNode)
return;
#if 0
switch(pNode->m_Type)
{
case HX_RE_VARIABLE:
printf (" Variable: %s\n", ((VariableNode *)pNode)->m_Data);
break;
case HX_RE_INTEGER:
printf (" Integer: %d\n", ((IntegerNode *)pNode)->m_Data);
break;
case HX_RE_FLOAT:
printf (" Float: %f\n", ((FloatNode *)pNode)->m_Data);
break;
case HX_RE_OPERATOR:
printf (" Operator: %s\n",
zpOpName[((OperatorNode *)pNode)->m_Data]);
break;
}
#endif
RDump(pNode->m_pLeft);
RDump(pNode->m_pRight);
}
void
ASMRuleExpression::RDelete(Node* pNode)
{
if (!pNode)
return;
if (pNode->m_Type == HX_RE_VARIABLE)
{
HX_VECTOR_DELETE(((VariableNode *)pNode)->m_Data);
};
RDelete(pNode->m_pLeft);
RDelete(pNode->m_pRight);
delete pNode;
}
/*
* This is a recursive expression evaluator that will determine whether
* or not we are subscribed to a particular rule, given the current conditions
*/
float
ASMRuleExpression::REvaluate(Node* pNode, IHXValues* pVars)
{
if (!pNode)
return (float)0;
switch(pNode->m_Type)
{
case HX_RE_VARIABLE:
{
IHXBuffer* pValue=NULL;
float nValue = (float)0;
pVars->GetPropertyCString(((VariableNode *)pNode)->m_Data, pValue);
if (pValue)
{
nValue = (float)atof((const char *)pValue->GetBuffer());
pValue->Release();
}
return nValue;
}
case HX_RE_INTEGER:
return (float)((IntegerNode *)pNode)->m_Data;
break;
case HX_RE_FLOAT:
return ((FloatNode *)pNode)->m_Data;
break;
case HX_RE_OPERATOR:
{
float Left = REvaluate(pNode->m_pLeft, pVars);
float Right = REvaluate(pNode->m_pRight, pVars);
switch (((OperatorNode *)pNode)->m_Data)
{
case HX_RE_GREATEREQUAL:
return (float)(Left >= Right);
break;
case HX_RE_GREATER:
return (float)(Left > Right);
break;
case HX_RE_LESSEQUAL:
if( Right == RULE_VAL_INFINITY )
{
return (float)TRUE;
}
return (float)(Left <= Right);
break;
case HX_RE_LESS:
if( Right == RULE_VAL_INFINITY )
{
return (float)TRUE;
}
return (float)(Left < Right);
break;
case HX_RE_EQUAL:
return (float)(Left == Right);
break;
case HX_RE_NOTEQUAL:
return (float)(Left != Right);
break;
case HX_RE_AND:
return (float)(Left && Right);
break;
case HX_RE_OR:
return (float)(Left || Right);
break;
default:
HX_ASSERT(0);
return (float)0;
break;
}
}
break;
default:
HX_ASSERT(0);
return (float)0;
break;
}
}
BOOL
ASMRuleExpression::Evaluate(IHXValues* pVars)
{
BOOL res;
//printf ("Evaluate ASMRuleExpression:\n");
res = (BOOL)REvaluate(m_pHead, pVars);
//printf ("%d\n", res);
return res;
}
/*
* This is a recursive function which will evaluate a tree with one free
* variable (pPrevar). The returned array will contain all possible values
* that are border cases.
*/
float
ASMRuleExpression::RPreEvaluate(Node* pNode, IHXValues* pVars,
const char* pPreVar, float*& pThreshold,
UINT32& ulNumThreshold,
BOOL& bInvolvesTheOpenVariable)
{
bInvolvesTheOpenVariable = FALSE;
float retval = 0;
float* pThresholdL = NULL;
float* pThresholdR = NULL;
#define RETURN(x) retval = x; goto exitpoint;
if (!pNode)
return (float)0;
switch(pNode->m_Type)
{
case HX_RE_VARIABLE:
{
IHXBuffer* pValue=NULL;
float nValue = (float)0;
pVars->GetPropertyCString(((VariableNode *)pNode)->m_Data, pValue);
if (pValue)
{
nValue = (float)atof((const char *)pValue->GetBuffer());
pValue->Release();
}
if (strcasecmp(((VariableNode *)pNode)->m_Data, pPreVar) == 0)
{
bInvolvesTheOpenVariable = TRUE;
}
return nValue;
}
case HX_RE_INTEGER:
return (float)((IntegerNode *)pNode)->m_Data;
break;
case HX_RE_FLOAT:
return ((FloatNode *)pNode)->m_Data;
break;
case HX_RE_OPERATOR:
{
BOOL bInvolveL, bInvolveR;
UINT32 ulNumThresholdL = 0;
pThresholdL = pThreshold;
float Left = RPreEvaluate(pNode->m_pLeft, pVars, pPreVar,
pThresholdL, ulNumThresholdL, bInvolveL);
UINT32 ulNumThresholdR = 0;
pThresholdR = pThreshold + ulNumThresholdL;
float Right = RPreEvaluate(pNode->m_pRight, pVars, pPreVar,
pThresholdR, ulNumThresholdR, bInvolveR);
/* Handle aggregation of Threshold arrays */
switch (((OperatorNode *)pNode)->m_Data)
{
case HX_RE_GREATEREQUAL:
case HX_RE_GREATER:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -