mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
MathParser: Converted to use WCHAR.
This commit is contained in:
parent
01b22e2d5e
commit
33d447a907
@ -756,11 +756,11 @@ double CConfigParser::ReadFormula(LPCTSTR section, LPCTSTR key, double defValue)
|
|||||||
if (!result.empty() && result[0] == L'(' && result[result.size() - 1] == L')')
|
if (!result.empty() && result[0] == L'(' && result[result.size() - 1] == L')')
|
||||||
{
|
{
|
||||||
double resultValue = defValue;
|
double resultValue = defValue;
|
||||||
char* errMsg = MathParser::CheckParse(ConvertToAscii(result.c_str()).c_str(), &resultValue);
|
WCHAR* errMsg = MathParser::CheckParse(result.c_str(), &resultValue);
|
||||||
if (errMsg != NULL)
|
if (errMsg != NULL)
|
||||||
{
|
{
|
||||||
std::wstring error = L"ReadFormula: ";
|
std::wstring error = L"ReadFormula: ";
|
||||||
error += ConvertToWide(errMsg);
|
error += errMsg;
|
||||||
error += L" in key \"";
|
error += L" in key \"";
|
||||||
error += key;
|
error += key;
|
||||||
error += L"\" in [";
|
error += L"\" in [";
|
||||||
@ -782,11 +782,11 @@ bool CConfigParser::ParseFormula(const std::wstring& result, double* resultValue
|
|||||||
// Formulas must be surrounded by parenthesis
|
// Formulas must be surrounded by parenthesis
|
||||||
if (!result.empty() && result[0] == L'(' && result[result.size() - 1] == L')')
|
if (!result.empty() && result[0] == L'(' && result[result.size() - 1] == L')')
|
||||||
{
|
{
|
||||||
char* errMsg = MathParser::CheckParse(ConvertToAscii(result.c_str()).c_str(), resultValue);
|
WCHAR* errMsg = MathParser::CheckParse(result.c_str(), resultValue);
|
||||||
if (errMsg != NULL)
|
if (errMsg != NULL)
|
||||||
{
|
{
|
||||||
std::wstring error = L"ParseFormula: ";
|
std::wstring error = L"ParseFormula: ";
|
||||||
error += ConvertToWide(errMsg);
|
error += errMsg;
|
||||||
error += L": ";
|
error += L": ";
|
||||||
error += result;
|
error += result;
|
||||||
Log(LOG_ERROR, error.c_str());
|
Log(LOG_ERROR, error.c_str());
|
||||||
|
@ -27,10 +27,10 @@ static const double M_E = 2.7182818284590452354;
|
|||||||
static const double M_PI = 3.14159265358979323846;
|
static const double M_PI = 3.14159265358979323846;
|
||||||
|
|
||||||
typedef double (*OneArgProc)(double arg);
|
typedef double (*OneArgProc)(double arg);
|
||||||
typedef char* (*MultiArgProc)(int paramcnt, double* args, double* result);
|
typedef WCHAR* (*MultiArgProc)(int paramcnt, double* args, double* result);
|
||||||
typedef double (*FunctionProc)(double);
|
typedef double (*FunctionProc)(double);
|
||||||
|
|
||||||
typedef enum
|
enum OperationType
|
||||||
{
|
{
|
||||||
OP_SHL,
|
OP_SHL,
|
||||||
OP_SHR,
|
OP_SHR,
|
||||||
@ -60,26 +60,19 @@ typedef enum
|
|||||||
OP_COMMA,
|
OP_COMMA,
|
||||||
OP_FUNC_ONEARG, // Special
|
OP_FUNC_ONEARG, // Special
|
||||||
OP_FUNC_MULTIARG // Special
|
OP_FUNC_MULTIARG // Special
|
||||||
} OperationType;
|
};
|
||||||
|
|
||||||
typedef struct
|
enum CharType
|
||||||
{
|
|
||||||
void* Func;
|
|
||||||
char prevvalTop;
|
|
||||||
OperationType type;
|
|
||||||
} Operation;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
{
|
||||||
|
CH_UNKNOWN = 0x00,
|
||||||
CH_LETTER = 0x01,
|
CH_LETTER = 0x01,
|
||||||
CH_DIGIT = 0x02,
|
CH_DIGIT = 0x02,
|
||||||
CH_SEPARAT = 0x04,
|
CH_SEPARAT = 0x04,
|
||||||
CH_SYMBOL = 0x08,
|
CH_SYMBOL = 0x08,
|
||||||
CH_UNKNOWN = 0x7E,
|
|
||||||
CH_FINAL = 0x7F
|
CH_FINAL = 0x7F
|
||||||
} CharType;
|
};
|
||||||
|
|
||||||
typedef enum
|
enum MathTokenType
|
||||||
{
|
{
|
||||||
TOK_ERROR,
|
TOK_ERROR,
|
||||||
TOK_NONE,
|
TOK_NONE,
|
||||||
@ -87,87 +80,61 @@ typedef enum
|
|||||||
TOK_FLOAT,
|
TOK_FLOAT,
|
||||||
TOK_SYMBOL,
|
TOK_SYMBOL,
|
||||||
TOK_NAME
|
TOK_NAME
|
||||||
} MathTokenType;
|
};
|
||||||
|
|
||||||
typedef struct
|
struct Operation
|
||||||
{
|
{
|
||||||
char* name;
|
void* proc;
|
||||||
|
BYTE prevTop;
|
||||||
|
OperationType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Function
|
||||||
|
{
|
||||||
|
WCHAR* name;
|
||||||
FunctionProc proc;
|
FunctionProc proc;
|
||||||
unsigned char length;
|
BYTE length;
|
||||||
} Function;
|
};
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
const char* string;
|
|
||||||
const char* name;
|
|
||||||
size_t nameLen;
|
|
||||||
double extValue;
|
|
||||||
int intValue;
|
|
||||||
MathTokenType PrevTokenType;
|
|
||||||
CharType CharType;
|
|
||||||
} Lexer;
|
|
||||||
|
|
||||||
char eBrackets [] = "Unmatched brackets";
|
|
||||||
char eSyntax [] = "Syntax error";
|
|
||||||
char eInternal [] = "Internal error";
|
|
||||||
char eExtraOp [] = "Extra operation";
|
|
||||||
char eInfinity [] = "Infinity somewhere";
|
|
||||||
char eInvArg [] = "Invalid argument";
|
|
||||||
char eUnknFunc [] = "\"%s\" is unknown";
|
|
||||||
char eLogicErr [] = "Logical expression error";
|
|
||||||
char eCalcErr [] = "Calculation error";
|
|
||||||
char eValSizErr[] = "Value too big for operation";
|
|
||||||
char eInvPrmCnt[] = "Invalid function parameter count";
|
|
||||||
char g_ErrorBuffer[128];
|
|
||||||
|
|
||||||
static char* CalcToObr();
|
|
||||||
static char* Calc();
|
|
||||||
static int GetFunction(const char* str, size_t len, void** data);
|
|
||||||
int FindSymbol(const char* str);
|
|
||||||
|
|
||||||
static int Lexer_SetParseString(const char* str);
|
|
||||||
static MathTokenType Lexer_GetNextToken();
|
|
||||||
|
|
||||||
static double neg(double x);
|
static double neg(double x);
|
||||||
static double frac(double x);
|
static double frac(double x);
|
||||||
static double trunc(double x);
|
static double trunc(double x);
|
||||||
static double sgn(double x);
|
static double sgn(double x);
|
||||||
static char* round(int paramcnt, double* args, double* result);
|
static WCHAR* round(int paramcnt, double* args, double* result);
|
||||||
|
|
||||||
static Function g_Functions[] =
|
static Function g_Functions[] =
|
||||||
{
|
{
|
||||||
{ "atan", &atan, 4 },
|
{ L"atan", &atan, 4 },
|
||||||
{ "cos", &cos, 3 },
|
{ L"cos", &cos, 3 },
|
||||||
{ "sin", &sin, 3 },
|
{ L"sin", &sin, 3 },
|
||||||
{ "tan", &tan, 3 },
|
{ L"tan", &tan, 3 },
|
||||||
{ "abs", &fabs, 3 },
|
{ L"abs", &fabs, 3 },
|
||||||
{ "exp", &exp, 3 },
|
{ L"exp", &exp, 3 },
|
||||||
{ "ln", &log, 2 },
|
{ L"ln", &log, 2 },
|
||||||
{ "log", &log10, 3 },
|
{ L"log", &log10, 3 },
|
||||||
{ "sqrt", &sqrt, 4 },
|
{ L"sqrt", &sqrt, 4 },
|
||||||
{ "frac", &frac, 4 },
|
{ L"frac", &frac, 4 },
|
||||||
{ "trunc", &trunc, 5 },
|
{ L"trunc", &trunc, 5 },
|
||||||
{ "floor", &floor, 5 },
|
{ L"floor", &floor, 5 },
|
||||||
{ "ceil", &ceil, 4 },
|
{ L"ceil", &ceil, 4 },
|
||||||
{ "round", (FunctionProc)&round, 5 },
|
{ L"round", (FunctionProc)&round, 5 },
|
||||||
{ "asin", &asin, 4 },
|
{ L"asin", &asin, 4 },
|
||||||
{ "acos", &acos, 4 },
|
{ L"acos", &acos, 4 },
|
||||||
{ "sgn", &sgn, 4 },
|
{ L"sgn", &sgn, 4 },
|
||||||
{ "neg", &neg, 4 },
|
{ L"neg", &neg, 4 },
|
||||||
{ "e", NULL, 1 },
|
{ L"e", NULL, 1 },
|
||||||
{ "pi", NULL, 2}
|
{ L"pi", NULL, 2}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int MAX_FUNC_LEN = 5;
|
static const int FUNC_MAX_LEN = 5;
|
||||||
|
static const int FUNC_ROUND = 13;
|
||||||
|
static const int FUNC_E = 18;
|
||||||
|
static const int FUNC_PI = 19;
|
||||||
|
|
||||||
#define FUNC_ROUND 13
|
static const Operation g_BrOp = { NULL, 0, OP_OBR };
|
||||||
#define FUNC_E 18
|
static const Operation g_NegOp = { (void*)&neg, 0, OP_FUNC_ONEARG };
|
||||||
#define FUNC_PI 19
|
|
||||||
|
|
||||||
static const Operation g_BrOp = { NULL, '0', OP_OBR };
|
static const BYTE g_OpPriorities[OP_FUNC_MULTIARG + 1] =
|
||||||
static const Operation g_NegOp = { (void*)&neg, '0', OP_FUNC_ONEARG };
|
|
||||||
|
|
||||||
static const char g_OpPriorities[OP_FUNC_MULTIARG + 1] =
|
|
||||||
{
|
{
|
||||||
5, // OP_SHL
|
5, // OP_SHL
|
||||||
5, // OP_SHR
|
5, // OP_SHR
|
||||||
@ -199,46 +166,66 @@ static const char g_OpPriorities[OP_FUNC_MULTIARG + 1] =
|
|||||||
6 // OP_FUNC_MULTIARG
|
6 // OP_FUNC_MULTIARG
|
||||||
};
|
};
|
||||||
|
|
||||||
static Operation g_OpStack[MAX_STACK_SIZE];
|
static CharType GetCharType(WCHAR ch);
|
||||||
static double g_ValStack[MAX_STACK_SIZE];
|
static int GetFunction(const WCHAR* str, size_t len, void** data);
|
||||||
static int g_OpTop = 0;
|
static int FindSymbol(const WCHAR* str);
|
||||||
static int g_ValTop = -1;
|
|
||||||
static int g_ObrDist = 0;
|
|
||||||
static CharType g_CharTypes[256] = {(CharType)0};
|
|
||||||
static Lexer g_Lexer = {0};
|
|
||||||
|
|
||||||
void MathParser::Initialize()
|
struct Parser
|
||||||
{
|
{
|
||||||
g_CharTypes['\0'] = CH_FINAL;
|
Operation opStack[MAX_STACK_SIZE];
|
||||||
|
double valStack[MAX_STACK_SIZE];
|
||||||
|
int opTop;
|
||||||
|
int valTop;
|
||||||
|
int obrDist;
|
||||||
|
|
||||||
g_CharTypes[' '] = g_CharTypes['\t'] = g_CharTypes['\n'] = CH_SEPARAT;
|
Parser() : opTop(0), valTop(-1), obrDist(2) { opStack[0].type = OP_OBR; }
|
||||||
|
};
|
||||||
|
|
||||||
g_CharTypes['_'] = CH_LETTER;
|
static WCHAR* CalcToObr(Parser& parser);
|
||||||
for (int ch = 'A'; ch <= 'Z'; ++ch) g_CharTypes[ch] = CH_LETTER;
|
static WCHAR* Calc(Parser& parser);
|
||||||
for (int ch = 'a'; ch <= 'z'; ++ch) g_CharTypes[ch] = CH_LETTER;
|
|
||||||
for (int ch = '0'; ch <= '9'; ++ch) g_CharTypes[ch] = CH_DIGIT;
|
|
||||||
|
|
||||||
g_CharTypes['+'] = g_CharTypes['-'] = g_CharTypes['/'] = g_CharTypes['*'] =
|
struct Lexer
|
||||||
g_CharTypes['~'] = g_CharTypes['('] = g_CharTypes[')'] = g_CharTypes['<'] =
|
{
|
||||||
g_CharTypes['>'] = g_CharTypes['%'] = g_CharTypes['$'] = g_CharTypes[','] =
|
const WCHAR* string;
|
||||||
g_CharTypes['?'] = g_CharTypes[':'] = g_CharTypes['='] = g_CharTypes['&'] =
|
const WCHAR* name;
|
||||||
g_CharTypes['|'] = CH_SYMBOL;
|
size_t nameLen;
|
||||||
}
|
double extValue;
|
||||||
|
int intValue;
|
||||||
|
MathTokenType prevToken;
|
||||||
|
CharType charType;
|
||||||
|
|
||||||
char* MathParser::Check(const char* formula)
|
Lexer(const WCHAR* str) : string(str), name(), nameLen(), extValue(), intValue(), prevToken(TOK_NONE), charType(GetCharType(*str)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
static MathTokenType GetNextToken(Lexer& lexer);
|
||||||
|
|
||||||
|
WCHAR eBrackets [] = L"Unmatched brackets";
|
||||||
|
WCHAR eSyntax [] = L"Syntax error";
|
||||||
|
WCHAR eInternal [] = L"Internal error";
|
||||||
|
WCHAR eExtraOp [] = L"Extra operation";
|
||||||
|
WCHAR eInfinity [] = L"Infinity somewhere";
|
||||||
|
WCHAR eInvArg [] = L"Invalid argument";
|
||||||
|
WCHAR eUnknFunc [] = L"\"%s\" is unknown";
|
||||||
|
WCHAR eLogicErr [] = L"Logical expression error";
|
||||||
|
WCHAR eCalcErr [] = L"Calculation error";
|
||||||
|
WCHAR eValSizErr[] = L"Value too big for operation";
|
||||||
|
WCHAR eInvPrmCnt[] = L"Invalid function parameter count";
|
||||||
|
WCHAR g_ErrorBuffer[128];
|
||||||
|
|
||||||
|
WCHAR* MathParser::Check(const WCHAR* formula)
|
||||||
{
|
{
|
||||||
int BrCnt = 0;
|
int BrCnt = 0;
|
||||||
|
|
||||||
// Brackets Matching
|
// Brackets Matching
|
||||||
while (*formula)
|
while (*formula)
|
||||||
{
|
{
|
||||||
if (*formula == '(')
|
if (*formula == L'(')
|
||||||
{
|
{
|
||||||
++BrCnt;
|
++BrCnt;
|
||||||
}
|
}
|
||||||
else if (*formula == ')' && (--BrCnt < 0))
|
else if (*formula == L')')
|
||||||
{
|
{
|
||||||
return eBrackets;
|
--BrCnt;
|
||||||
}
|
}
|
||||||
++formula;
|
++formula;
|
||||||
}
|
}
|
||||||
@ -251,76 +238,82 @@ char* MathParser::Check(const char* formula)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* MathParser::CheckParse(const char* formula, double* result)
|
WCHAR* MathParser::CheckParse(const WCHAR* formula, double* result)
|
||||||
{
|
{
|
||||||
char* ret = Check(formula);
|
WCHAR* error = Check(formula);
|
||||||
if (ret) return ret;
|
if (!error)
|
||||||
|
{
|
||||||
ret = Parse(formula, NULL, result);
|
error = Parse(formula, NULL, result);
|
||||||
if (ret) return ret;
|
}
|
||||||
|
return error;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char* MathParser::Parse(const char* formula, CMeasureCalc* calc, double* result)
|
WCHAR* MathParser::Parse(const WCHAR* formula, CMeasureCalc* calc, double* result)
|
||||||
{
|
{
|
||||||
if (!formula || !*formula)
|
if (!*formula)
|
||||||
{
|
{
|
||||||
*result = 0.0;
|
*result = 0.0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lexer_SetParseString(formula);
|
Parser parser;
|
||||||
|
Lexer lexer(formula);
|
||||||
|
|
||||||
g_OpTop = 0;
|
WCHAR* error;
|
||||||
g_ValTop = -1;
|
|
||||||
g_OpStack[0].type = OP_OBR;
|
|
||||||
g_ObrDist = 2;
|
|
||||||
|
|
||||||
char* error;
|
|
||||||
MathTokenType token = Lexer_GetNextToken();
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
--g_ObrDist;
|
MathTokenType token = GetNextToken(lexer);
|
||||||
|
--parser.obrDist;
|
||||||
switch (token)
|
switch (token)
|
||||||
{
|
{
|
||||||
case TOK_ERROR:
|
case TOK_ERROR:
|
||||||
return eSyntax;
|
return eSyntax;
|
||||||
|
|
||||||
case TOK_FINAL:
|
case TOK_FINAL:
|
||||||
if ((error = CalcToObr()) != NULL)
|
if ((error = CalcToObr(parser)) != NULL)
|
||||||
|
{
|
||||||
return error;
|
return error;
|
||||||
goto setResult;
|
}
|
||||||
|
else if (parser.opTop != -1 || parser.valTop != 0)
|
||||||
|
{
|
||||||
|
return eInternal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Done!
|
||||||
|
*result = parser.valStack[0];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case TOK_FLOAT:
|
case TOK_FLOAT:
|
||||||
g_ValStack[++g_ValTop] = g_Lexer.extValue;
|
parser.valStack[++parser.valTop] = lexer.extValue;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_SYMBOL:
|
case TOK_SYMBOL:
|
||||||
switch (g_Lexer.intValue)
|
switch (lexer.intValue)
|
||||||
{
|
{
|
||||||
case OP_OBR: // (
|
case OP_OBR:
|
||||||
{
|
{
|
||||||
g_OpStack[++g_OpTop] = g_BrOp;
|
parser.opStack[++parser.opTop] = g_BrOp;
|
||||||
g_ObrDist = 2;
|
parser.obrDist = 2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_CBR: //)
|
case OP_CBR:
|
||||||
{
|
{
|
||||||
if ((error = CalcToObr()) != NULL) return error;
|
if ((error = CalcToObr(parser)) != NULL) return error;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_COMMA: // ,
|
case OP_COMMA:
|
||||||
{
|
{
|
||||||
Operation* pOp;
|
if ((error = CalcToObr(parser)) != NULL) return error;
|
||||||
if ((error = CalcToObr()) != NULL) return error;
|
|
||||||
|
|
||||||
if ((pOp = &g_OpStack[g_OpTop])->type == OP_FUNC_MULTIARG)
|
if (parser.opStack[parser.opTop].type == OP_FUNC_MULTIARG)
|
||||||
{
|
{
|
||||||
g_OpStack[++g_OpTop] = g_BrOp;
|
parser.opStack[++parser.opTop] = g_BrOp;
|
||||||
g_ObrDist = 2;
|
parser.obrDist = 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -332,81 +325,86 @@ char* MathParser::Parse(const char* formula, CMeasureCalc* calc, double* result)
|
|||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
Operation op;
|
Operation op;
|
||||||
op.type = (OperationType) g_Lexer.intValue;
|
op.type = (OperationType)lexer.intValue;
|
||||||
switch (op.type)
|
switch (op.type)
|
||||||
{
|
{
|
||||||
case OP_ADD:
|
case OP_ADD:
|
||||||
if (g_ObrDist >= 1) goto nextToken;
|
if (parser.obrDist >= 1)
|
||||||
|
{
|
||||||
|
// Goto next token
|
||||||
|
continue;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_SUB:
|
case OP_SUB:
|
||||||
if (g_ObrDist >= 1)
|
if (parser.obrDist >= 1)
|
||||||
{
|
{
|
||||||
g_OpStack[++g_OpTop] = g_NegOp;
|
parser.opStack[++parser.opTop] = g_NegOp;
|
||||||
goto nextToken;
|
|
||||||
|
// Goto next token
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_LOGIC:
|
case OP_LOGIC:
|
||||||
case OP_LOGIC_SEP:
|
case OP_LOGIC_SEP:
|
||||||
g_ObrDist = 2;
|
parser.obrDist = 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (g_OpPriorities[op.type] <= g_OpPriorities[g_OpStack[g_OpTop].type])
|
while (g_OpPriorities[op.type] <= g_OpPriorities[parser.opStack[parser.opTop].type])
|
||||||
{
|
{
|
||||||
if ((error = Calc()) != NULL) return error;
|
if ((error = Calc(parser)) != NULL) return error;
|
||||||
}
|
}
|
||||||
g_OpStack[++g_OpTop] = op;
|
parser.opStack[++parser.opTop] = op;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_NAME:
|
case TOK_NAME:
|
||||||
{
|
{
|
||||||
Operation op;
|
Operation op;
|
||||||
double dblval;
|
int funcnum, namelen = lexer.nameLen;
|
||||||
void* *func = NULL;
|
|
||||||
int funcnum, namelen = g_Lexer.nameLen;
|
|
||||||
|
|
||||||
if (g_Lexer.nameLen <= MAX_FUNC_LEN &&
|
if (lexer.nameLen <= FUNC_MAX_LEN &&
|
||||||
((funcnum = GetFunction(g_Lexer.name, g_Lexer.nameLen, (void**)&op.Func)) >= 0))
|
((funcnum = GetFunction(lexer.name, lexer.nameLen, (void**)&op.proc)) >= 0))
|
||||||
{
|
{
|
||||||
switch (funcnum)
|
switch (funcnum)
|
||||||
{
|
{
|
||||||
case FUNC_E:
|
case FUNC_E:
|
||||||
g_ValStack[++g_ValTop] = M_E;
|
parser.valStack[++parser.valTop] = M_E;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FUNC_PI:
|
case FUNC_PI:
|
||||||
g_ValStack[++g_ValTop] = M_PI;
|
parser.valStack[++parser.valTop] = M_PI;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FUNC_ROUND:
|
case FUNC_ROUND:
|
||||||
op.type = OP_FUNC_MULTIARG;
|
op.type = OP_FUNC_MULTIARG;
|
||||||
op.prevvalTop = g_ValTop;
|
op.prevTop = parser.valTop;
|
||||||
g_OpStack[++g_OpTop] = op;
|
parser.opStack[++parser.opTop] = op;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // Internal function
|
default: // Internal function
|
||||||
op.type = OP_FUNC_ONEARG;
|
op.type = OP_FUNC_ONEARG;
|
||||||
g_OpStack[++g_OpTop] = op;
|
parser.opStack[++parser.opTop] = op;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (calc && calc->GetMeasureValue(g_Lexer.name, g_Lexer.nameLen, &dblval))
|
double dblval;
|
||||||
|
if (calc && calc->GetMeasureValue(lexer.name, lexer.nameLen, &dblval))
|
||||||
{
|
{
|
||||||
g_ValStack[++g_ValTop] = dblval;
|
parser.valStack[++parser.valTop] = dblval;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buffer[128 - _countof(eUnknFunc)];
|
WCHAR buffer[128 - _countof(eUnknFunc)];
|
||||||
strncpy_s(buffer, g_Lexer.name, g_Lexer.nameLen);
|
wcsncpy_s(buffer, lexer.name, lexer.nameLen);
|
||||||
buffer[g_Lexer.nameLen] = '\0';
|
buffer[lexer.nameLen] = L'\0';
|
||||||
_snprintf_s(g_ErrorBuffer, _TRUNCATE, eUnknFunc, buffer);
|
_snwprintf_s(g_ErrorBuffer, _TRUNCATE, eUnknFunc, buffer);
|
||||||
return g_ErrorBuffer;
|
return g_ErrorBuffer;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -415,46 +413,37 @@ char* MathParser::Parse(const char* formula, CMeasureCalc* calc, double* result)
|
|||||||
default:
|
default:
|
||||||
return eSyntax;
|
return eSyntax;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextToken:
|
|
||||||
token = Lexer_GetNextToken();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setResult:
|
|
||||||
if (g_OpTop != -1 || g_ValTop != 0) return eInternal;
|
|
||||||
|
|
||||||
*result = g_ValStack[0];
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* Calc()
|
static WCHAR* Calc(Parser& parser)
|
||||||
{
|
{
|
||||||
double res;
|
double res;
|
||||||
Operation op = g_OpStack[g_OpTop--];
|
Operation op = parser.opStack[parser.opTop--];
|
||||||
|
|
||||||
// Multi-argument function
|
// Multi-argument function
|
||||||
if (op.type == OP_FUNC_MULTIARG)
|
if (op.type == OP_FUNC_MULTIARG)
|
||||||
{
|
{
|
||||||
int paramcnt = g_ValTop - op.prevvalTop;
|
int paramcnt = parser.valTop - op.prevTop;
|
||||||
|
|
||||||
g_ValTop = op.prevvalTop;
|
parser.valTop = op.prevTop;
|
||||||
char* error = (*(MultiArgProc)op.Func)(paramcnt, &g_ValStack[g_ValTop + 1], &res);
|
WCHAR* error = (*(MultiArgProc)op.proc)(paramcnt, &parser.valStack[parser.valTop + 1], &res);
|
||||||
if (error) return error;
|
if (error) return error;
|
||||||
|
|
||||||
g_ValStack[++g_ValTop] = res;
|
parser.valStack[++parser.valTop] = res;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (op.type == OP_LOGIC)
|
else if (op.type == OP_LOGIC)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (g_ValTop < 0)
|
else if (parser.valTop < 0)
|
||||||
{
|
{
|
||||||
return eExtraOp;
|
return eExtraOp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right arg
|
// Right arg
|
||||||
double right = g_ValStack[g_ValTop--];
|
double right = parser.valStack[parser.valTop--];
|
||||||
|
|
||||||
// One arg operations
|
// One arg operations
|
||||||
if (op.type == OP_NOT)
|
if (op.type == OP_NOT)
|
||||||
@ -470,17 +459,17 @@ static char* Calc()
|
|||||||
}
|
}
|
||||||
else if (op.type == OP_FUNC_ONEARG)
|
else if (op.type == OP_FUNC_ONEARG)
|
||||||
{
|
{
|
||||||
res = (*(OneArgProc)op.Func)(right);
|
res = (*(OneArgProc)op.proc)(right);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (g_ValTop < 0)
|
if (parser.valTop < 0)
|
||||||
{
|
{
|
||||||
return eExtraOp;
|
return eExtraOp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Left arg
|
// Left arg
|
||||||
double left = g_ValStack[g_ValTop--];
|
double left = parser.valStack[parser.valTop--];
|
||||||
switch (op.type)
|
switch (op.type)
|
||||||
{
|
{
|
||||||
case OP_SHL:
|
case OP_SHL:
|
||||||
@ -620,11 +609,11 @@ static char* Calc()
|
|||||||
{
|
{
|
||||||
// needs three arguments
|
// needs three arguments
|
||||||
double ValLL;
|
double ValLL;
|
||||||
if (g_OpTop < 0 || g_OpStack[g_OpTop--].type != OP_LOGIC)
|
if (parser.opTop < 0 || parser.opStack[parser.opTop--].type != OP_LOGIC)
|
||||||
{
|
{
|
||||||
return eLogicErr;
|
return eLogicErr;
|
||||||
}
|
}
|
||||||
ValLL = g_ValStack[g_ValTop--];
|
ValLL = parser.valStack[parser.valTop--];
|
||||||
res = ValLL ? left : right;
|
res = ValLL ? left : right;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -634,91 +623,31 @@ static char* Calc()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_ValStack[++g_ValTop] = res;
|
parser.valStack[++parser.valTop] = res;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* CalcToObr()
|
static WCHAR* CalcToObr(Parser& parser)
|
||||||
{
|
{
|
||||||
while (g_OpStack[g_OpTop].type != OP_OBR)
|
while (parser.opStack[parser.opTop].type != OP_OBR)
|
||||||
{
|
{
|
||||||
char* error = Calc();
|
WCHAR* error = Calc(parser);
|
||||||
if (error) return error;
|
if (error) return error;
|
||||||
}
|
}
|
||||||
--g_OpTop;
|
--parser.opTop;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetFunction(const char* str, size_t len, void** data)
|
MathTokenType GetNextToken(Lexer& lexer)
|
||||||
{
|
|
||||||
const int funcCount = sizeof(g_Functions) / sizeof(Function);
|
|
||||||
for (int i = 0; i < funcCount; ++i)
|
|
||||||
{
|
|
||||||
if (g_Functions[i].length == len &&
|
|
||||||
_strnicmp(str, g_Functions[i].name, len) == 0)
|
|
||||||
{
|
|
||||||
*data = g_Functions[i].proc;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FindSymbol(const char* str)
|
|
||||||
{
|
|
||||||
switch (str[0])
|
|
||||||
{
|
|
||||||
case '(': return (int)OP_OBR;
|
|
||||||
case '+': return OP_ADD;
|
|
||||||
case '-': return OP_SUB;
|
|
||||||
case '*': return (str[1] == '*') ? OP_POW : OP_MUL;
|
|
||||||
case '/': return OP_DIV;
|
|
||||||
case '%': return OP_MOD;
|
|
||||||
case '$': return OP_UNK;
|
|
||||||
case '^': return OP_XOR;
|
|
||||||
case '~': return OP_NOT;
|
|
||||||
case '&': return (str[1] == '&') ? OP_LOGIC_AND : OP_AND;
|
|
||||||
case '|': return (str[1] == '|') ? OP_LOGIC_OR : OP_OR;
|
|
||||||
case '=': return OP_EQU;
|
|
||||||
case '>': return (str[1] == '>') ? OP_SHR : (str[1] == '=') ? OP_LOGIC_GEQ : OP_GREATER;
|
|
||||||
case '<': return (str[1] == '>') ? OP_LOGIC_NEQ : (str[1] == '<') ? OP_SHL : (str[1] == '=') ? OP_LOGIC_LEQ : OP_SMALLER;
|
|
||||||
case '?': return OP_LOGIC;
|
|
||||||
case ':': return OP_LOGIC_SEP;
|
|
||||||
case ')': return OP_CBR;
|
|
||||||
case ',': return OP_COMMA;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------
|
|
||||||
// Lexer
|
|
||||||
// -----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
inline CharType CHARTYPEPP() { return g_CharTypes[(unsigned char)*++(g_Lexer.string)]; }
|
|
||||||
inline CharType CHARTYPE() { return g_CharTypes[(unsigned char)*g_Lexer.string]; }
|
|
||||||
|
|
||||||
int Lexer_SetParseString(const char* str)
|
|
||||||
{
|
|
||||||
g_Lexer.PrevTokenType = TOK_NONE;
|
|
||||||
if (!str || !*str) return 0;
|
|
||||||
|
|
||||||
g_Lexer.string = str;
|
|
||||||
g_Lexer.CharType = CHARTYPE();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
MathTokenType Lexer_GetNextToken()
|
|
||||||
{
|
{
|
||||||
MathTokenType result = TOK_ERROR;
|
MathTokenType result = TOK_ERROR;
|
||||||
|
|
||||||
while (g_Lexer.CharType == CH_SEPARAT)
|
while (lexer.charType == CH_SEPARAT)
|
||||||
{
|
{
|
||||||
g_Lexer.CharType = CHARTYPEPP();
|
lexer.charType = GetCharType(*++lexer.string);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (g_Lexer.CharType)
|
switch (lexer.charType)
|
||||||
{
|
{
|
||||||
case CH_FINAL:
|
case CH_FINAL:
|
||||||
{
|
{
|
||||||
@ -728,36 +657,36 @@ MathTokenType Lexer_GetNextToken()
|
|||||||
|
|
||||||
case CH_LETTER:
|
case CH_LETTER:
|
||||||
{
|
{
|
||||||
g_Lexer.name = g_Lexer.string;
|
lexer.name = lexer.string;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
g_Lexer.CharType = CHARTYPEPP();
|
lexer.charType = GetCharType(*++lexer.string);
|
||||||
}
|
}
|
||||||
while (g_Lexer.CharType <= CH_DIGIT);
|
while (lexer.charType <= CH_DIGIT);
|
||||||
|
|
||||||
g_Lexer.nameLen = g_Lexer.string - g_Lexer.name;
|
lexer.nameLen = lexer.string - lexer.name;
|
||||||
result = TOK_NAME;
|
result = TOK_NAME;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CH_DIGIT:
|
case CH_DIGIT:
|
||||||
{
|
{
|
||||||
char* newString;
|
WCHAR* newString;
|
||||||
if (g_Lexer.string[0] == '0')
|
if (lexer.string[0] == L'0')
|
||||||
{
|
{
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
switch (g_Lexer.string[1])
|
switch (lexer.string[1])
|
||||||
{
|
{
|
||||||
case 'x': // Hexadecimal
|
case L'x': // Hexadecimal
|
||||||
g_Lexer.intValue = strtol(g_Lexer.string, &newString, 16);
|
lexer.intValue = wcstol(lexer.string, &newString, 16);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o': // Octal
|
case L'o': // Octal
|
||||||
g_Lexer.intValue = strtol(g_Lexer.string + 2, &newString, 8);
|
lexer.intValue = wcstol(lexer.string + 2, &newString, 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b': // Binary
|
case L'b': // Binary
|
||||||
g_Lexer.intValue = strtol(g_Lexer.string + 2, &newString, 2);
|
lexer.intValue = wcstol(lexer.string + 2, &newString, 2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -767,11 +696,11 @@ MathTokenType Lexer_GetNextToken()
|
|||||||
|
|
||||||
if (valid)
|
if (valid)
|
||||||
{
|
{
|
||||||
if (g_Lexer.string != newString)
|
if (lexer.string != newString)
|
||||||
{
|
{
|
||||||
g_Lexer.string = newString;
|
lexer.string = newString;
|
||||||
g_Lexer.CharType = CHARTYPE();
|
lexer.charType = GetCharType(*lexer.string);
|
||||||
g_Lexer.extValue = g_Lexer.intValue;
|
lexer.extValue = lexer.intValue;
|
||||||
result = TOK_FLOAT;
|
result = TOK_FLOAT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -779,11 +708,11 @@ MathTokenType Lexer_GetNextToken()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decimal
|
// Decimal
|
||||||
g_Lexer.extValue = strtod(g_Lexer.string, &newString);
|
lexer.extValue = wcstod(lexer.string, &newString);
|
||||||
if (g_Lexer.string != newString)
|
if (lexer.string != newString)
|
||||||
{
|
{
|
||||||
g_Lexer.string = newString;
|
lexer.string = newString;
|
||||||
g_Lexer.CharType = CHARTYPE();
|
lexer.charType = GetCharType(*lexer.string);
|
||||||
result = TOK_FLOAT;
|
result = TOK_FLOAT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -791,16 +720,13 @@ MathTokenType Lexer_GetNextToken()
|
|||||||
|
|
||||||
case CH_SYMBOL:
|
case CH_SYMBOL:
|
||||||
{
|
{
|
||||||
int sym = FindSymbol(g_Lexer.string);
|
int sym = FindSymbol(lexer.string);
|
||||||
if (sym >= 0)
|
if (sym >= 0)
|
||||||
{
|
{
|
||||||
g_Lexer.string += (sym == OP_POW ||
|
lexer.string += (sym <= OP_LOGIC_OR) ? 2 : 1;
|
||||||
sym == OP_LOGIC_AND || sym == OP_LOGIC_OR ||
|
|
||||||
sym == OP_SHR || sym == OP_LOGIC_GEQ ||
|
|
||||||
sym == OP_LOGIC_NEQ || sym == OP_SHL || sym == OP_LOGIC_LEQ) ? 2 : 1;
|
|
||||||
|
|
||||||
g_Lexer.CharType = CHARTYPE();
|
lexer.charType = GetCharType(*lexer.string);
|
||||||
g_Lexer.intValue = sym;
|
lexer.intValue = sym;
|
||||||
result = TOK_SYMBOL;
|
result = TOK_SYMBOL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -809,7 +735,97 @@ MathTokenType Lexer_GetNextToken()
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return g_Lexer.PrevTokenType = result;
|
return lexer.prevToken = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CharType GetCharType(WCHAR ch)
|
||||||
|
{
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case L'\0':
|
||||||
|
return CH_FINAL;
|
||||||
|
|
||||||
|
case L' ':
|
||||||
|
case L'\t':
|
||||||
|
case L'\n':
|
||||||
|
return CH_SEPARAT;
|
||||||
|
|
||||||
|
case L'_':
|
||||||
|
return CH_LETTER;
|
||||||
|
|
||||||
|
case L'+':
|
||||||
|
case L'-':
|
||||||
|
case L'/':
|
||||||
|
case L'*':
|
||||||
|
case L'~':
|
||||||
|
case L'(':
|
||||||
|
case L')':
|
||||||
|
case L'<':
|
||||||
|
case L'>':
|
||||||
|
case L'%':
|
||||||
|
case L'$':
|
||||||
|
case L',':
|
||||||
|
case L'?':
|
||||||
|
case L':':
|
||||||
|
case L'=':
|
||||||
|
case L'&':
|
||||||
|
case L'|':
|
||||||
|
return CH_SYMBOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iswalpha(ch)) return CH_LETTER;
|
||||||
|
if (iswdigit(ch)) return CH_DIGIT;
|
||||||
|
|
||||||
|
return CH_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MathParser::IsDelimiter(WCHAR ch)
|
||||||
|
{
|
||||||
|
CharType type = GetCharType(ch);
|
||||||
|
return type == CH_SYMBOL || type == CH_SEPARAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetFunction(const WCHAR* str, size_t len, void** data)
|
||||||
|
{
|
||||||
|
const int funcCount = sizeof(g_Functions) / sizeof(Function);
|
||||||
|
for (int i = 0; i < funcCount; ++i)
|
||||||
|
{
|
||||||
|
if (g_Functions[i].length == len &&
|
||||||
|
_wcsnicmp(str, g_Functions[i].name, len) == 0)
|
||||||
|
{
|
||||||
|
*data = g_Functions[i].proc;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FindSymbol(const WCHAR* str)
|
||||||
|
{
|
||||||
|
switch (str[0])
|
||||||
|
{
|
||||||
|
case L'(': return (int)OP_OBR;
|
||||||
|
case L'+': return OP_ADD;
|
||||||
|
case L'-': return OP_SUB;
|
||||||
|
case L'*': return (str[1] == L'*') ? OP_POW : OP_MUL;
|
||||||
|
case L'/': return OP_DIV;
|
||||||
|
case L'%': return OP_MOD;
|
||||||
|
case L'$': return OP_UNK;
|
||||||
|
case L'^': return OP_XOR;
|
||||||
|
case L'~': return OP_NOT;
|
||||||
|
case L'&': return (str[1] == L'&') ? OP_LOGIC_AND : OP_AND;
|
||||||
|
case L'|': return (str[1] == L'|') ? OP_LOGIC_OR : OP_OR;
|
||||||
|
case L'=': return OP_EQU;
|
||||||
|
case L'>': return (str[1] == L'>') ? OP_SHR : (str[1] == L'=') ? OP_LOGIC_GEQ : OP_GREATER;
|
||||||
|
case L'<': return (str[1] == L'>') ? OP_LOGIC_NEQ : (str[1] == L'<') ? OP_SHL : (str[1] == L'=') ? OP_LOGIC_LEQ : OP_SMALLER;
|
||||||
|
case L'?': return OP_LOGIC;
|
||||||
|
case L':': return OP_LOGIC_SEP;
|
||||||
|
case L')': return OP_CBR;
|
||||||
|
case L',': return OP_COMMA;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------
|
||||||
@ -838,7 +854,7 @@ static double neg(double x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "Advanced" round function; second argument - sharpness
|
// "Advanced" round function; second argument - sharpness
|
||||||
static char* round(int paramcnt, double* args, double* result)
|
static WCHAR* round(int paramcnt, double* args, double* result)
|
||||||
{
|
{
|
||||||
int sharpness;
|
int sharpness;
|
||||||
if (paramcnt == 1)
|
if (paramcnt == 1)
|
||||||
|
@ -25,11 +25,11 @@ class CMeasureCalc;
|
|||||||
|
|
||||||
namespace MathParser
|
namespace MathParser
|
||||||
{
|
{
|
||||||
void Initialize();
|
WCHAR* Check(const WCHAR* formula);
|
||||||
|
WCHAR* CheckParse(const WCHAR* formula, double* result);
|
||||||
|
WCHAR* Parse(const WCHAR* formula, CMeasureCalc* calc, double* result);
|
||||||
|
|
||||||
char* Check(const char* formula);
|
bool IsDelimiter(WCHAR ch);
|
||||||
char* CheckParse(const char* formula, double* result);
|
|
||||||
char* Parse(const char* formula, CMeasureCalc* calc, double* result);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -30,7 +30,6 @@ bool CMeasureCalc::c_RandSeeded = false;
|
|||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
CMeasureCalc::CMeasureCalc(CMeterWindow* meterWindow, const WCHAR* name) : CMeasure(meterWindow, name),
|
CMeasureCalc::CMeasureCalc(CMeterWindow* meterWindow, const WCHAR* name) : CMeasure(meterWindow, name),
|
||||||
m_Random(),
|
|
||||||
m_LowBound(),
|
m_LowBound(),
|
||||||
m_HighBound(100),
|
m_HighBound(100),
|
||||||
m_UpdateRandom(false)
|
m_UpdateRandom(false)
|
||||||
@ -64,13 +63,11 @@ bool CMeasureCalc::Update()
|
|||||||
{
|
{
|
||||||
if (!CMeasure::PreUpdate()) return false;
|
if (!CMeasure::PreUpdate()) return false;
|
||||||
|
|
||||||
if (m_UpdateRandom) UpdateRandom();
|
WCHAR* errMsg = MathParser::Parse(m_Formula.c_str(), this, &m_Value);
|
||||||
|
|
||||||
char* errMsg = MathParser::Parse(ConvertToAscii(m_Formula.c_str()).c_str(), this, &m_Value);
|
|
||||||
if (errMsg != NULL)
|
if (errMsg != NULL)
|
||||||
{
|
{
|
||||||
std::wstring error = L"Calc: ";
|
std::wstring error = L"Calc: ";
|
||||||
error += ConvertToWide(errMsg);
|
error += errMsg;
|
||||||
error += L" in [";
|
error += L" in [";
|
||||||
error += m_Name;
|
error += m_Name;
|
||||||
error += L']';
|
error += L']';
|
||||||
@ -108,13 +105,16 @@ void CMeasureCalc::ReadConfig(CConfigParser& parser, const WCHAR* section)
|
|||||||
oldHighBound != m_HighBound ||
|
oldHighBound != m_HighBound ||
|
||||||
oldUpdateRandom != m_UpdateRandom)
|
oldUpdateRandom != m_UpdateRandom)
|
||||||
{
|
{
|
||||||
if (!m_UpdateRandom) UpdateRandom();
|
if (!m_UpdateRandom)
|
||||||
|
{
|
||||||
|
FormulaReplace();
|
||||||
|
}
|
||||||
|
|
||||||
char* errMsg = MathParser::Check(ConvertToAscii(m_Formula.c_str()).c_str());
|
WCHAR* errMsg = MathParser::Check(m_Formula.c_str());
|
||||||
if (errMsg != NULL)
|
if (errMsg != NULL)
|
||||||
{
|
{
|
||||||
std::wstring error = L"Calc: ";
|
std::wstring error = L"Calc: ";
|
||||||
error += ConvertToWide(errMsg);
|
error += errMsg;
|
||||||
error += L" in [";
|
error += L" in [";
|
||||||
error += m_Name;
|
error += m_Name;
|
||||||
error += L']';
|
error += L']';
|
||||||
@ -122,38 +122,72 @@ void CMeasureCalc::ReadConfig(CConfigParser& parser, const WCHAR* section)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
** FormulaReplace
|
||||||
|
**
|
||||||
|
** This replaces the word Random in the formula with a random number
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
void CMeasureCalc::FormulaReplace()
|
||||||
|
{
|
||||||
|
size_t start = 0, pos;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
pos = m_Formula.find_first_of(L"Rr", start);
|
||||||
|
if (pos != std::wstring::npos)
|
||||||
|
{
|
||||||
|
if (_wcsnicmp(L"random", m_Formula.c_str() + pos, 6) == 0 &&
|
||||||
|
(pos == 0 || MathParser::IsDelimiter((*(m_Formula.c_str() + pos - 1))) &&
|
||||||
|
(pos == (m_Formula.length() - 6) || MathParser::IsDelimiter((*(m_Formula.c_str() + pos + 6))))))
|
||||||
|
{
|
||||||
|
int randNumber = GetRandom();
|
||||||
|
|
||||||
bool CMeasureCalc::GetMeasureValue(const char* str, int len, double* value)
|
WCHAR buffer[32];
|
||||||
|
_itow_s(randNumber, buffer, 10);
|
||||||
|
size_t len = wcslen(buffer);
|
||||||
|
|
||||||
|
m_Formula.replace(pos, 6, buffer, len);
|
||||||
|
start = pos + len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start = pos + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (pos != std::wstring::npos);
|
||||||
|
}
|
||||||
|
bool CMeasureCalc::GetMeasureValue(const WCHAR* str, int len, double* value)
|
||||||
{
|
{
|
||||||
const std::list<CMeasure*>& measures = m_MeterWindow->GetMeasures();
|
const std::list<CMeasure*>& measures = m_MeterWindow->GetMeasures();
|
||||||
|
|
||||||
std::list<CMeasure*>::const_iterator iter = measures.begin();
|
std::list<CMeasure*>::const_iterator iter = measures.begin();
|
||||||
for ( ; iter != measures.end(); ++iter)
|
for ( ; iter != measures.end(); ++iter)
|
||||||
{
|
{
|
||||||
if (_strnicmp(str, (*iter)->GetAsciiName(), len) == 0)
|
if (_wcsnicmp(str, (*iter)->GetName(), len) == 0)
|
||||||
{
|
{
|
||||||
*value = (*iter)->GetValue();
|
*value = (*iter)->GetValue();
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_strnicmp(str, "counter", len) == 0)
|
if (_wcsnicmp(str, L"counter", len) == 0)
|
||||||
{
|
{
|
||||||
*value = m_MeterWindow->GetUpdateCounter();
|
*value = m_MeterWindow->GetUpdateCounter();
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
else if (_strnicmp(str, "random", len) == 0)
|
else if (_wcsnicmp(str, L"random", len) == 0)
|
||||||
{
|
{
|
||||||
*value = (double)m_Random;
|
*value = GetRandom();
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMeasureCalc::UpdateRandom()
|
int CMeasureCalc::GetRandom()
|
||||||
{
|
{
|
||||||
int range = (m_HighBound - m_LowBound) + 1;
|
int range = (m_HighBound - m_LowBound) + 1;
|
||||||
srand((unsigned)rand());
|
srand((unsigned)rand());
|
||||||
m_Random = m_LowBound + (int)(range * rand() / (RAND_MAX + 1.0));
|
return m_LowBound + (int)(range * rand() / (RAND_MAX + 1.0));
|
||||||
}
|
}
|
||||||
|
@ -29,20 +29,20 @@ public:
|
|||||||
|
|
||||||
virtual bool Update();
|
virtual bool Update();
|
||||||
|
|
||||||
bool GetMeasureValue(const char* str, int len, double* value);
|
bool GetMeasureValue(const WCHAR* str, int len, double* value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void ReadConfig(CConfigParser& parser, const WCHAR* section);
|
virtual void ReadConfig(CConfigParser& parser, const WCHAR* section);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateRandom();
|
void FormulaReplace();
|
||||||
|
int GetRandom();
|
||||||
|
|
||||||
std::wstring m_Formula;
|
std::wstring m_Formula;
|
||||||
|
|
||||||
int m_Random;
|
|
||||||
|
|
||||||
int m_LowBound;
|
int m_LowBound;
|
||||||
int m_HighBound;
|
int m_HighBound;
|
||||||
|
|
||||||
bool m_UpdateRandom;
|
bool m_UpdateRandom;
|
||||||
|
|
||||||
static bool c_RandSeeded;
|
static bool c_RandSeeded;
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#include "Error.h"
|
#include "Error.h"
|
||||||
#include "DialogAbout.h"
|
#include "DialogAbout.h"
|
||||||
#include "DialogManage.h"
|
#include "DialogManage.h"
|
||||||
#include "MathParser.h"
|
|
||||||
#include "MeasureNet.h"
|
#include "MeasureNet.h"
|
||||||
#include "MeterString.h"
|
#include "MeterString.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
@ -1068,7 +1067,6 @@ int CRainmeter::Initialize(HWND hParent, HINSTANCE hInstance, LPCWSTR szPath)
|
|||||||
// Test that the Rainmeter.ini file is writable
|
// Test that the Rainmeter.ini file is writable
|
||||||
TestSettingsFile(bDefaultIniLocation);
|
TestSettingsFile(bDefaultIniLocation);
|
||||||
|
|
||||||
MathParser::Initialize();
|
|
||||||
CSystem::Initialize(hInstance);
|
CSystem::Initialize(hInstance);
|
||||||
CMeasureNet::InitializeNewApi();
|
CMeasureNet::InitializeNewApi();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user