Removed ccalc and replaced with MathParser

This commit is contained in:
Birunthan Mohanathas 2012-01-22 20:28:05 +00:00
parent f373ea0b1e
commit caf0a60a5b
18 changed files with 974 additions and 1403 deletions

View File

@ -18,6 +18,7 @@
#include "StdAfx.h"
#include "ConfigParser.h"
#include "MathParser.h"
#include "Litestep.h"
#include "Rainmeter.h"
#include "System.h"
@ -37,7 +38,6 @@ std::unordered_map<std::wstring, std::wstring> CConfigParser::c_MonitorVariables
**
*/
CConfigParser::CConfigParser() :
m_Parser(MathParser_Create(NULL)),
m_LastReplaced(false),
m_LastDefaultUsed(false),
m_LastValueDefined(false),
@ -53,7 +53,6 @@ CConfigParser::CConfigParser() :
*/
CConfigParser::~CConfigParser()
{
MathParser_Destroy(m_Parser);
}
/*
@ -757,7 +756,7 @@ double CConfigParser::ReadFormula(LPCTSTR section, LPCTSTR key, double defValue)
if (!result.empty() && result[0] == L'(' && result[result.size() - 1] == L')')
{
double resultValue = defValue;
char* errMsg = MathParser_Parse(m_Parser, ConvertToAscii(result.c_str()).c_str(), &resultValue);
char* errMsg = MathParser::CheckParse(ConvertToAscii(result.c_str()).c_str(), &resultValue);
if (errMsg != NULL)
{
std::wstring error = L"ReadFormula: ";
@ -783,7 +782,7 @@ bool CConfigParser::ParseFormula(const std::wstring& result, double* resultValue
// Formulas must be surrounded by parenthesis
if (!result.empty() && result[0] == L'(' && result[result.size() - 1] == L')')
{
char* errMsg = MathParser_Parse(m_Parser, ConvertToAscii(result.c_str()).c_str(), resultValue);
char* errMsg = MathParser::CheckParse(ConvertToAscii(result.c_str()).c_str(), resultValue);
if (errMsg != NULL)
{
std::wstring error = L"ParseFormula: ";

View File

@ -28,7 +28,6 @@
#include <unordered_map>
#include <algorithm>
#include <gdiplus.h>
#include "ccalc-0.5.1/mparser.h"
class CRainmeter;
class CMeterWindow;
@ -122,7 +121,6 @@ private:
std::wstring m_Filename;
hqMathParser* m_Parser;
std::unordered_map<std::wstring, CMeasure*> m_Measures;
std::vector<std::wstring> m_StyleTemplate;

View File

@ -333,6 +333,17 @@
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Use</PrecompiledHeader>
</ClCompile>
<ClCompile Include="MathParser.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">EnableFastChecks</BasicRuntimeChecks>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Use</PrecompiledHeader>
</ClCompile>
<ClCompile Include="Measure.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
@ -721,30 +732,6 @@
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Use</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ccalc-0.5.1\lexer.c">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">EnableFastChecks</BasicRuntimeChecks>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
</ClCompile>
<ClCompile Include="ccalc-0.5.1\mparser.c">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">EnableFastChecks</BasicRuntimeChecks>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
</ClCompile>
<ClCompile Include="ccalc-0.5.1\strmap.c">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">EnableFastChecks</BasicRuntimeChecks>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
</ClCompile>
<ClCompile Include="lua\LuaManager.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>
@ -855,6 +842,7 @@
<ClInclude Include="Group.h" />
<ClInclude Include="Litestep.h" />
<ClInclude Include="DialogManage.h" />
<ClInclude Include="MathParser.h" />
<ClInclude Include="Measure.h" />
<ClInclude Include="MeasureCalc.h" />
<ClInclude Include="MeasureCPU.h" />
@ -896,10 +884,6 @@
<ClInclude Include="TintedImage.h" />
<ClInclude Include="TrayWindow.h" />
<ClInclude Include="UpdateCheck.h" />
<ClInclude Include="ccalc-0.5.1\lexer.h" />
<ClInclude Include="ccalc-0.5.1\mparser.h" />
<ClInclude Include="ccalc-0.5.1\pack.h" />
<ClInclude Include="ccalc-0.5.1\strmap.h" />
<ClInclude Include="lua\LuaManager.h" />
<ClInclude Include="lua\LuaScript.h" />
<ClInclude Include="lua\include\lua.hpp" />

View File

@ -13,9 +13,6 @@
<UniqueIdentifier>{2d6bf39d-48e1-4de3-8924-46c5666cb141}</UniqueIdentifier>
<Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
</Filter>
<Filter Include="CCalc">
<UniqueIdentifier>{1d914071-7b9c-400c-b7ab-76ac461a16f3}</UniqueIdentifier>
</Filter>
<Filter Include="Lua">
<UniqueIdentifier>{6570e2b7-2e40-4fba-a051-01de85760fea}</UniqueIdentifier>
</Filter>
@ -144,15 +141,6 @@
<ClCompile Include="UpdateCheck.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ccalc-0.5.1\lexer.c">
<Filter>CCalc</Filter>
</ClCompile>
<ClCompile Include="ccalc-0.5.1\mparser.c">
<Filter>CCalc</Filter>
</ClCompile>
<ClCompile Include="ccalc-0.5.1\strmap.c">
<Filter>CCalc</Filter>
</ClCompile>
<ClCompile Include="lua\LuaManager.cpp">
<Filter>Lua</Filter>
</ClCompile>
@ -354,6 +342,9 @@
<ClCompile Include="Export.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MathParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ConfigParser.h">
@ -476,18 +467,6 @@
<ClInclude Include="UpdateCheck.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ccalc-0.5.1\lexer.h">
<Filter>CCalc</Filter>
</ClInclude>
<ClInclude Include="ccalc-0.5.1\mparser.h">
<Filter>CCalc</Filter>
</ClInclude>
<ClInclude Include="ccalc-0.5.1\pack.h">
<Filter>CCalc</Filter>
</ClInclude>
<ClInclude Include="ccalc-0.5.1\strmap.h">
<Filter>CCalc</Filter>
</ClInclude>
<ClInclude Include="lua\LuaManager.h">
<Filter>Lua</Filter>
</ClInclude>
@ -596,6 +575,12 @@
<ClInclude Include="Export.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RawString.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MathParser.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Library.rc">

877
Library/MathParser.cpp Normal file
View File

@ -0,0 +1,877 @@
/*
Copyright (C) 2011 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNEstring FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// Heavily based on ccalc 0.5.1 by Walery Studennikov <hqsoftware@mail.ru>
#include "StdAfx.h"
#include "MathParser.h"
static const int MAX_STACK_SIZE = 32;
static const double M_E = 2.7182818284590452354;
static const double M_PI = 3.14159265358979323846;
typedef double (*OneArgProc)(double arg);
typedef char* (*MultiArgProc)(int paramcnt, double* args, double* result);
typedef double (*FunctionProc)(double);
typedef enum
{
OP_SHL,
OP_SHR,
OP_POW,
OP_LOGIC_NEQ,
OP_LOGIC_GEQ,
OP_LOGIC_LEQ,
OP_LOGIC_AND,
OP_LOGIC_OR,
OP_OBR,
OP_ADD,
OP_SUB,
OP_MUL,
OP_DIV,
OP_MOD,
OP_UNK,
OP_XOR,
OP_NOT,
OP_AND,
OP_OR,
OP_EQU,
OP_GREATER,
OP_SMALLER,
OP_LOGIC,
OP_LOGIC_SEP,
OP_CBR,
OP_COMMA,
OP_FUNC_ONEARG, // Special
OP_FUNC_MULTIARG // Special
} OperationType;
typedef struct
{
void* Func;
char prevvalTop;
OperationType type;
} Operation;
typedef enum
{
CH_LETTER = 0x01,
CH_DIGIT = 0x02,
CH_SEPARAT = 0x04,
CH_SYMBOL = 0x08,
CH_UNKNOWN = 0x7E,
CH_FINAL = 0x7F
} CharType;
typedef enum
{
TOK_ERROR,
TOK_NONE,
TOK_FINAL,
TOK_FLOAT,
TOK_SYMBOL,
TOK_NAME
} MathTokenType;
typedef struct
{
char* name;
FunctionProc proc;
unsigned char 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 frac(double x);
static double trunc(double x);
static double sgn(double x);
static char* round(int paramcnt, double* args, double* result);
static Function g_Functions[] =
{
{ "atan", &atan, 4 },
{ "cos", &cos, 3 },
{ "sin", &sin, 3 },
{ "tan", &tan, 3 },
{ "abs", &fabs, 3 },
{ "exp", &exp, 3 },
{ "ln", &log, 2 },
{ "log", &log10, 3 },
{ "sqrt", &sqrt, 4 },
{ "frac", &frac, 4 },
{ "trunc", &trunc, 5 },
{ "floor", &floor, 5 },
{ "ceil", &ceil, 4 },
{ "round", (FunctionProc)&round, 5 },
{ "asin", &asin, 4 },
{ "acos", &acos, 4 },
{ "sgn", &sgn, 4 },
{ "neg", &neg, 4 },
{ "e", NULL, 1 },
{ "pi", NULL, 2}
};
static const int MAX_FUNC_LEN = 5;
#define FUNC_ROUND 13
#define FUNC_E 18
#define FUNC_PI 19
static const Operation g_BrOp = { NULL, '0', OP_OBR };
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_SHR
5, // OP_POW
2, // OP_LOGIC_NEQ
2, // OP_LOGIC_GEQ
2, // OP_LOGIC_LEQ
2, // OP_LOGIC_AND
2, // OP_LOGIC_OR
0, // OP_OBR
3, // OP_ADD
3, // OP_SUB
4, // OP_MUL
4, // OP_DIV
4, // OP_MOD
4, // OP_UNK
5, // OP_XOR
5, // OP_NOT
5, // OP_AND
5, // OP_OR
2, // OP_EQU
2, // OP_GREATER
2, // OP_SMALLER
1, // OP_LOGIC
2, // OP_LOGIC_SEP
0, // OP_CBR
2, // OP_COMMA
6, // OP_FUNC_ONEARG
6 // OP_FUNC_MULTIARG
};
static Operation g_OpStack[MAX_STACK_SIZE];
static double g_ValStack[MAX_STACK_SIZE];
static int g_OpTop = 0;
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()
{
g_CharTypes['\0'] = CH_FINAL;
g_CharTypes[' '] = g_CharTypes['\t'] = g_CharTypes['\n'] = CH_SEPARAT;
g_CharTypes['_'] = CH_LETTER;
for (int ch = 'A'; ch <= 'Z'; ++ch) g_CharTypes[ch] = CH_LETTER;
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['*'] =
g_CharTypes['~'] = g_CharTypes['('] = g_CharTypes[')'] = g_CharTypes['<'] =
g_CharTypes['>'] = g_CharTypes['%'] = g_CharTypes['$'] = g_CharTypes[','] =
g_CharTypes['?'] = g_CharTypes[':'] = g_CharTypes['='] = g_CharTypes['&'] =
g_CharTypes['|'] = CH_SYMBOL;
}
char* MathParser::Check(const char* formula)
{
int BrCnt = 0;
// Brackets Matching
while (*formula)
{
if (*formula == '(')
{
++BrCnt;
}
else if (*formula == ')' && (--BrCnt < 0))
{
return eBrackets;
}
++formula;
}
if (BrCnt != 0)
{
return eBrackets;
}
return NULL;
}
char* MathParser::CheckParse(const char* formula, double* result)
{
char* ret = Check(formula);
if (ret) return ret;
ret = Parse(formula, NULL, result);
if (ret) return ret;
return NULL;
}
char* MathParser::Parse(const char* formula, ParameterSearchProc searchProc, double* result)
{
if (!formula || !*formula)
{
*result = 0.0;
return NULL;
}
Lexer_SetParseString(formula);
g_OpTop = 0;
g_ValTop = -1;
g_OpStack[0].type = OP_OBR;
g_ObrDist = 2;
char* error;
MathTokenType token = Lexer_GetNextToken();
for (;;)
{
--g_ObrDist;
switch (token)
{
case TOK_ERROR:
return eSyntax;
case TOK_FINAL:
if ((error = CalcToObr()) != NULL)
return error;
goto setResult;
case TOK_FLOAT:
g_ValStack[++g_ValTop] = g_Lexer.extValue;
break;
case TOK_SYMBOL:
switch (g_Lexer.intValue)
{
case OP_OBR: // (
{
g_OpStack[++g_OpTop] = g_BrOp;
g_ObrDist = 2;
}
break;
case OP_CBR: //)
{
if ((error = CalcToObr()) != NULL) return error;
}
break;
case OP_COMMA: // ,
{
Operation* pOp;
if ((error = CalcToObr()) != NULL) return error;
if ((pOp = &g_OpStack[g_OpTop])->type == OP_FUNC_MULTIARG)
{
g_OpStack[++g_OpTop] = g_BrOp;
g_ObrDist = 2;
}
else
{
return eSyntax;
}
}
break;
default:
{
Operation op;
op.type = (OperationType) g_Lexer.intValue;
switch (op.type)
{
case OP_ADD:
if (g_ObrDist >= 1) goto nextToken;
break;
case OP_SUB:
if (g_ObrDist >= 1)
{
g_OpStack[++g_OpTop] = g_NegOp;
goto nextToken;
}
break;
case OP_LOGIC:
case OP_LOGIC_SEP:
g_ObrDist = 2;
break;
}
while (g_OpPriorities[op.type] <= g_OpPriorities[g_OpStack[g_OpTop].type])
{
if ((error = Calc()) != NULL) return error;
}
g_OpStack[++g_OpTop] = op;
}
break;
}
break;
case TOK_NAME:
{
Operation op;
double dblval;
void* *func = NULL;
int funcnum, namelen = g_Lexer.nameLen;
if (g_Lexer.nameLen <= MAX_FUNC_LEN &&
((funcnum = GetFunction(g_Lexer.name, g_Lexer.nameLen, (void**)&op.Func)) >= 0))
{
switch (funcnum)
{
case FUNC_E:
g_ValStack[++g_ValTop] = M_E;
break;
case FUNC_PI:
g_ValStack[++g_ValTop] = M_PI;
break;
case FUNC_ROUND:
op.type = OP_FUNC_MULTIARG;
op.prevvalTop = g_ValTop;
g_OpStack[++g_OpTop] = op;
break;
default: // Internal function
op.type = OP_FUNC_ONEARG;
g_OpStack[++g_OpTop] = op;
break;
}
}
else
{
if (searchProc && (*searchProc)(g_Lexer.name, g_Lexer.nameLen, &dblval))
{
g_ValStack[++g_ValTop] = dblval;
break;
}
char buffer[128 - _countof(eUnknFunc)];
strncpy_s(buffer, g_Lexer.name, g_Lexer.nameLen);
buffer[g_Lexer.nameLen] = '\0';
_snprintf_s(g_ErrorBuffer, _TRUNCATE, eUnknFunc, buffer);
return g_ErrorBuffer;
}
break;
}
default:
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()
{
double res;
Operation op = g_OpStack[g_OpTop--];
// Multi-argument function
if (op.type == OP_FUNC_MULTIARG)
{
int paramcnt = g_ValTop - op.prevvalTop;
g_ValTop = op.prevvalTop;
char* error = (*(MultiArgProc)op.Func)(paramcnt, &g_ValStack[g_ValTop + 1], &res);
if (error) return error;
g_ValStack[++g_ValTop] = res;
return NULL;
}
else if (op.type == OP_LOGIC)
{
return NULL;
}
else if (g_ValTop < 0)
{
return eExtraOp;
}
// Right arg
double right = g_ValStack[g_ValTop--];
// One arg operations
if (op.type == OP_NOT)
{
if (right >= INT_MIN && right <= INT_MAX)
{
res = ~((int)right);
}
else
{
return eValSizErr;
}
}
else if (op.type == OP_FUNC_ONEARG)
{
res = (*(OneArgProc)op.Func)(right);
}
else
{
if (g_ValTop < 0)
{
return eExtraOp;
}
// Left arg
double left = g_ValStack[g_ValTop--];
switch (op.type)
{
case OP_SHL:
if (left >= INT_MIN && left <= INT_MAX && right >= INT_MIN && right <= INT_MAX)
{
res = (int)left << (int)right;
}
else
{
return eValSizErr;
}
break;
case OP_SHR:
if (left >= INT_MIN && left <= INT_MAX && right >= INT_MIN && right <= INT_MAX)
{
res = (int)left >> (int)right;
}
else
{
return eValSizErr;
}
break;
case OP_POW:
res = pow(left, right);
break;
case OP_LOGIC_NEQ:
res = left != right;
break;
case OP_LOGIC_GEQ:
res = left >= right;
break;
case OP_LOGIC_LEQ:
res = left <= right;
break;
case OP_LOGIC_AND:
res = left && right;
break;
case OP_LOGIC_OR:
res = left || right;
break;
case OP_ADD:
res = left + right;
break;
case OP_SUB:
res = left - right;
break;
case OP_MUL:
res = left* right;
break;
case OP_DIV:
if (right == 0.0)
{
return eInfinity;
}
else
{
res = left / right;
}
break;
case OP_MOD:
res = fmod(left, right);
break;
case OP_UNK:
if (left <= 0)
{
res = 0.0;
}
else if (right == 0.0)
{
return eInfinity;
}
else
{
res = ceil(left / right);
}
break;
case OP_XOR:
if (left >= INT_MIN && left <= INT_MAX && right >= INT_MIN && right <= INT_MAX)
{
res = (int)left ^ (int)right;
}
else
{
return eValSizErr;
}
break;
case OP_AND:
if (left >= INT_MIN && left <= INT_MAX && right >= INT_MIN && right <= INT_MAX)
{
res = (int)left & (int)right;
}
else
{
return eValSizErr;
}
break;
case OP_OR:
if (left >= INT_MIN && left <= INT_MAX && right >= INT_MIN && right <= INT_MAX)
{
res = (int)left | (int)right;
}
else
{
return eValSizErr;
}
break;
case OP_EQU:
res = left == right;
break;
case OP_GREATER:
res = left > right;
break;
case OP_SMALLER:
res = left < right;
break;
case OP_LOGIC_SEP:
{
// needs three arguments
double ValLL;
if (g_OpTop < 0 || g_OpStack[g_OpTop--].type != OP_LOGIC)
{
return eLogicErr;
}
ValLL = g_ValStack[g_ValTop--];
res = ValLL ? left : right;
}
break;
default:
return eInternal;
}
}
g_ValStack[++g_ValTop] = res;
return NULL;
}
static char* CalcToObr()
{
while (g_OpStack[g_OpTop].type != OP_OBR)
{
char* error = Calc();
if (error) return error;
}
--g_OpTop;
return NULL;
}
int GetFunction(const char* 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 &&
_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;
while (g_Lexer.CharType == CH_SEPARAT)
{
g_Lexer.CharType = CHARTYPEPP();
}
switch (g_Lexer.CharType)
{
case CH_FINAL:
{
result = TOK_FINAL;
}
break;
case CH_LETTER:
{
g_Lexer.name = g_Lexer.string;
do
{
g_Lexer.CharType = CHARTYPEPP();
}
while (g_Lexer.CharType <= CH_DIGIT);
g_Lexer.nameLen = g_Lexer.string - g_Lexer.name;
result = TOK_NAME;
}
break;
case CH_DIGIT:
{
char* newString;
if (g_Lexer.string[0] == '0')
{
bool valid = true;
switch (g_Lexer.string[1])
{
case 'x': // Hexadecimal
g_Lexer.intValue = strtol(g_Lexer.string, &newString, 16);
break;
case 'o': // Octal
g_Lexer.intValue = strtol(g_Lexer.string + 2, &newString, 8);
break;
case 'b': // Binary
g_Lexer.intValue = strtol(g_Lexer.string + 2, &newString, 2);
break;
default:
valid = false;
break;
}
if (valid)
{
if (g_Lexer.string != newString)
{
g_Lexer.string = newString;
g_Lexer.CharType = CHARTYPE();
g_Lexer.extValue = g_Lexer.intValue;
result = TOK_FLOAT;
}
break;
}
}
// Decimal
g_Lexer.extValue = strtod(g_Lexer.string, &newString);
if (g_Lexer.string != newString)
{
g_Lexer.string = newString;
g_Lexer.CharType = CHARTYPE();
result = TOK_FLOAT;
}
}
break;
case CH_SYMBOL:
{
int sym = FindSymbol(g_Lexer.string);
if (sym >= 0)
{
g_Lexer.string += (sym == OP_POW ||
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();
g_Lexer.intValue = sym;
result = TOK_SYMBOL;
}
}
break;
default:
break;
}
return g_Lexer.PrevTokenType = result;
}
// -----------------------------------------------------------------------------------------------
// Misc
// -----------------------------------------------------------------------------------------------
static double frac(double x)
{
double y;
return modf(x, &y);
}
static double trunc(double x)
{
return (x >= 0.0) ? floor(x) : ceil(x);
}
static double sgn(double x)
{
return (x > 0) ? 1 : (x < 0) ? -1 : 0;
}
static double neg(double x)
{
return -x;
}
// "Advanced" round function; second argument - sharpness
static char* round(int paramcnt, double* args, double* result)
{
int sharpness;
if (paramcnt == 1)
{
sharpness = 0;
}
else if (paramcnt == 2)
{
sharpness = (int)args[1];
}
else
{
return eInvPrmCnt;
}
double x = args[0];
double coef;
if (sharpness < 0)
{
coef = 0.1;
sharpness = -sharpness;
}
else
{
coef = 10;
}
for (int i = 0; i < sharpness; i++) x *= coef;
x = (x + ((x >= 0) ? 0.5 : -0.5));
x = (x >= 0.0) ? floor(x) : ceil(x);
for (int i = 0; i < sharpness; i++) x /= coef;
*result = x;
return NULL;
}

35
Library/MathParser.h Normal file
View File

@ -0,0 +1,35 @@
/*
Copyright (C) 2011 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// Heavily based on ccalc 0.5.1 by Walery Studennikov <hqsoftware@mail.ru>
#ifndef __MATHPARSER_H__
#define __MATHPARSER_H__
namespace MathParser
{
typedef int (*ParameterSearchProc)(const char* str, int len, double* value);
void Initialize();
char* Check(const char* formula);
char* CheckParse(const char* formula, double* result);
char* Parse(const char* formula, ParameterSearchProc searchProc, double* result);
};
#endif

View File

@ -19,8 +19,9 @@
#include "StdAfx.h"
#include "MeasureCalc.h"
#include "Rainmeter.h"
#include "MathParser.h"
hqStrMap* CMeasureCalc::c_VarMap = NULL;
CMeterWindow* CMeasureCalc::c_MeterWindow = NULL;
bool CMeasureCalc::c_RandSeeded = false;
/*
@ -30,7 +31,6 @@ bool CMeasureCalc::c_RandSeeded = false;
**
*/
CMeasureCalc::CMeasureCalc(CMeterWindow* meterWindow, const WCHAR* name) : CMeasure(meterWindow, name),
m_Parser(MathParser_Create(NULL)),
m_LowBound(),
m_HighBound(100),
m_UpdateRandom(false)
@ -52,13 +52,6 @@ CMeasureCalc::CMeasureCalc(CMeterWindow* meterWindow, const WCHAR* name) : CMeas
*/
CMeasureCalc::~CMeasureCalc()
{
MathParser_Destroy(m_Parser);
if (c_VarMap)
{
StrMap_Destroy(c_VarMap);
c_VarMap = NULL;
}
}
/*
@ -71,13 +64,12 @@ bool CMeasureCalc::Update()
{
if (!CMeasure::PreUpdate()) return false;
m_Parser->Parameters = c_VarMap;
if (m_UpdateRandom)
{
FormulaReplace();
}
char* errMsg = MathParser_Parse(m_Parser, ConvertToAscii(m_Formula.c_str()).c_str(), &m_Value);
char* errMsg = MathParser::Parse(ConvertToAscii(m_Formula.c_str()).c_str(), MatchMeasure, &m_Value);
if (errMsg != NULL)
{
std::wstring error = L"Calc: ";
@ -91,32 +83,27 @@ bool CMeasureCalc::Update()
return PostUpdate();
}
void CMeasureCalc::UpdateVariableMap(CMeterWindow& meterWindow)
int CMeasureCalc::MatchMeasure(const char* str, int len, double* value)
{
// Delete the old map
if (c_VarMap)
{
StrMap_Destroy(c_VarMap);
c_VarMap = NULL;
}
// Create the variable map
c_VarMap = Strmap_Create(sizeof(double), 0);
const std::list<CMeasure*>& measures = meterWindow.GetMeasures();
const std::list<CMeasure*>& measures = c_MeterWindow->GetMeasures();
std::list<CMeasure*>::const_iterator iter = measures.begin();
for ( ; iter != measures.end(); ++iter)
{
const char* name = (*iter)->GetAsciiName();
double val = (*iter)->GetValue();
StrMap_AddString(c_VarMap, name, &val);
if (_strnicmp(str, (*iter)->GetAsciiName(), len) == 0)
{
*value = (*iter)->GetValue();
return 1;
}
}
// Add the counter
double counter = meterWindow.GetUpdateCounter();
StrMap_AddString(c_VarMap, "Counter", &counter);
if (_strnicmp(str, "counter", len) == 0)
{
*value = c_MeterWindow->GetUpdateCounter();
return 1;
}
return 0;
}
/*
@ -153,6 +140,17 @@ void CMeasureCalc::ReadConfig(CConfigParser& parser, const WCHAR* section)
{
FormulaReplace();
}
char* errMsg = MathParser::Check(ConvertToAscii(m_Formula.c_str()).c_str());
if (errMsg != NULL)
{
std::wstring error = L"Calc: ";
error += ConvertToWide(errMsg);
error += L" in [";
error += m_Name;
error += L']';
throw CError(error);
}
}
}
@ -164,8 +162,8 @@ void CMeasureCalc::ReadConfig(CConfigParser& parser, const WCHAR* section)
*/
void CMeasureCalc::FormulaReplace()
{
//To implement random numbers the word "Random" in the string
//formula is being replaced by the random number value
// To implement random numbers the word "Random" in the string
// formula is being replaced by the random number value
m_Formula = m_FormulaHolder;
size_t start = 0, pos;

View File

@ -20,7 +20,6 @@
#define __MEASURECALC_H__
#include "Measure.h"
#include "ccalc-0.5.1/mparser.h"
class CMeasureCalc : public CMeasure
{
@ -30,7 +29,7 @@ public:
virtual bool Update();
static void UpdateVariableMap(CMeterWindow& meterWindow);
static void SetCurrentMeterWindow(CMeterWindow* meterWindow) { c_MeterWindow = meterWindow; }
protected:
virtual void ReadConfig(CConfigParser& parser, const WCHAR* section);
@ -39,15 +38,16 @@ private:
void FormulaReplace();
bool IsDelimiter(WCHAR ch);
static int MatchMeasure(const char* str, int len, double* value);
std::wstring m_Formula;
std::wstring m_FormulaHolder;
hqMathParser* m_Parser;
int m_LowBound;
int m_HighBound;
bool m_UpdateRandom;
static hqStrMap* c_VarMap;
static CMeterWindow* c_MeterWindow;
static bool c_RandSeeded;
};

View File

@ -1417,7 +1417,7 @@ void CMeterWindow::UpdateMeasure(const WCHAR* name, bool group)
// Pre-updates
if (!m_Measures.empty())
{
CMeasureCalc::UpdateVariableMap(*this);
CMeasureCalc::SetCurrentMeterWindow(this);
}
bool bNetStats = m_HasNetMeasures;
@ -2944,7 +2944,7 @@ void CMeterWindow::Update(bool nodraw)
CMeasureNet::UpdateIFTable();
CMeasureNet::UpdateStats();
}
CMeasureCalc::UpdateVariableMap(*this);
CMeasureCalc::SetCurrentMeterWindow(this);
// Update all measures
std::list<CMeasure*>::const_iterator i = m_Measures.begin();

View File

@ -23,6 +23,7 @@
#include "Error.h"
#include "DialogAbout.h"
#include "DialogManage.h"
#include "MathParser.h"
#include "MeasureNet.h"
#include "MeterString.h"
#include "resource.h"
@ -1067,6 +1068,7 @@ int CRainmeter::Initialize(HWND hParent, HINSTANCE hInstance, LPCWSTR szPath)
// Test that the Rainmeter.ini file is writable
TestSettingsFile(bDefaultIniLocation);
MathParser::Initialize();
CSystem::Initialize(hInstance);
CMeasureNet::InitializeNewApi();

View File

@ -1,290 +0,0 @@
/*
Universal lexical analiser implementation
*/
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include "lexer.h"
//#define MY_DEBUG 1
#ifdef MY_DEBUG
#include <stdio.h>
#endif
/* Uppercase translation table for the Win1251 charset */
const char Win1251UpcaseTbl[] =
"\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017"
"\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
" !\042#$%&'()*+,-./0123456789:;<=>?"
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
"`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\177"
"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337";
char Win1251RusLetters[] =
"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377";
hqCharType Win1251NameTbl[256];
int win1251nametbl_initialized = 0;
int FindSymbol( SymbolRec **SymTable, const char *str, int *nchars );
// initializations
void InitCharTypeTable( hqCharType *CharTypeTable, int CharTypes )
{
int ch;
#ifdef MY_DEBUG
printf( "CharTypeTable = 0x%X; CharTypes = %d\n", (unsigned)CharTypeTable,
CharTypes );
#endif
memset( CharTypeTable, CH_UNKNOWN, 256 * sizeof(hqCharType) );
CharTypeTable[0] = CH_FINAL;
if (CharTypes & CH_SEPARAT) {
CharTypeTable[' '] = CH_SEPARAT;
CharTypeTable[9] = CH_SEPARAT;
CharTypeTable[13] = CH_SEPARAT;
CharTypeTable[10] = CH_SEPARAT;
}
if (CharTypes & CH_QUOTE) {
CharTypeTable['\''] = CH_QUOTE;
}
if (CharTypes & CH_LETTER) {
for (ch='A'; ch<='Z'; ch++)
CharTypeTable[ch] = CH_LETTER;
for (ch='a'; ch<='z'; ch++)
CharTypeTable[ch] = CH_LETTER;
CharTypeTable['_'] = CH_LETTER;
}
if (CharTypes & CH_DIGIT) {
for (ch='0'; ch<='9'; ch++)
CharTypeTable[ch] = CH_DIGIT;
}
}
void TypeTableAddChars( hqCharType *CharTypeTable, char *Symbols,
hqCharType CharType )
{
while (*Symbols)
CharTypeTable[ (uchar) *Symbols++] = CharType;
}
void UpcaseWin1251Str( char *Str )
{
while (( *Str = Win1251UpcaseTbl[ (uchar) *Str ] ))
++Str;
}
// hqLexer implementation
#define CHARTYPEPP lexer->CharTypeTable[ (uchar) *++(lexer->SS) ]
#define CHARTYPE lexer->CharTypeTable[ (uchar) *lexer->SS ]
int Lexer_SetParseString( hqLexer *lexer, const char *str )
{
lexer->PrevTokenType = TOK_NONE;
if ( !str || !*str )
return 0;
lexer->SS = str;
lexer->CharType = CHARTYPE;
return 1;
}
hqTokenType Lexer_GetNextToken( hqLexer *lexer )
{
hqTokenType result = TOK_ERROR;
next_token:
while ( lexer->CharType == CH_SEPARAT )
lexer->CharType = CHARTYPEPP;
switch ( lexer->CharType ) {
case CH_FINAL:
result = TOK_FINAL;
break;
case CH_LETTER:
lexer->Name = lexer->SS;
do {
lexer->CharType = CHARTYPEPP;
} while (lexer->CharType <= CH_DIGIT);
lexer->NameLen = lexer->SS - lexer->Name;
result = TOK_NAME;
break;
case CH_DIGIT: {
char *NewSS, ch = *lexer->SS, nch = *(lexer->SS+1);
int intreaded = 0;
// Readind hex number
if ( ch == '0' && nch == 'x' ) {
lexer->IntValue = strtol( lexer->SS, &NewSS, 16 );
intreaded = 1;
}
// Readind oct number
if ( ch == '0' && nch == 'o') { // original version: if ( ch == '0' && nch >= '0' && nch <='9')
lexer->IntValue = strtol( lexer->SS+2, &NewSS, 8 );
intreaded = 1;
}
// Readind bin number
if ( ch == '0' && nch == 'b') { // original version: if ( ch == '0' && nch >= '0' && nch <='9')
lexer->IntValue = strtol( lexer->SS+2, &NewSS, 2 );
intreaded = 1;
}
if (intreaded == 1) {
if ( lexer->SS != NewSS ) {
lexer->SS = NewSS;
if (lexer->NoIntegers) {
lexer->ExtValue = lexer->IntValue;
result = TOK_FLOAT;
} else
result = TOK_INT;
lexer->CharType = CHARTYPE;
}
break;
}
// Readind dec number
lexer->ExtValue = strtod( lexer->SS, &NewSS );
if ( lexer->SS != NewSS ) {;
lexer->SS = NewSS;
if ( !lexer->NoIntegers
&& lexer->ExtValue<=INT_MAX
&& lexer->ExtValue>=INT_MAX
&& (double)( lexer->IntValue = (uchar) lexer->ExtValue )
== lexer->ExtValue ) {
result = TOK_INT;
} else
result = TOK_FLOAT;
lexer->CharType = CHARTYPE;
}
break;
}
case CH_SYMBOL: {
int nchars;
int i = FindSymbol( lexer->SymTable, lexer->SS, &nchars );
if (i >= 0) {
lexer->SS += nchars;
if (i == lexer->cssn) {
char comend = *lexer->ComEnd;
char comendpp = *(lexer->ComEnd+1);
while ( *lexer->SS ) {
if ( *lexer->SS == comend
&&
( comendpp == '\0' || *(lexer->SS+1) == comendpp )
) {
++lexer->SS;
if (comendpp != '\0')
++lexer->SS;
lexer->CharType = CHARTYPE;
goto next_token;
}
++lexer->SS;
}
break;
}
lexer->CharType = CHARTYPE;
lexer->IntValue = i;
result = TOK_SYMBOL;
}
break;
}
case CH_QUOTE:
lexer->Name = ++(lexer->SS);
while ( lexer->CharTypeTable[ (uchar)*lexer->SS ] != CH_QUOTE
&& *(lexer->SS) != '\0' )
++lexer->SS;
if ( CHARTYPE == CH_QUOTE ) {
lexer->NameLen = lexer->SS - lexer->Name;
++lexer->SS;
lexer->CharType = CHARTYPE;
result = TOK_STRING;
}
break;
default:
break;
}
return lexer->PrevTokenType = result;
}
const char* Lexer_GetCurrentPos( hqLexer *lexer )
{
return lexer->SS;
}
// misc functions
void PrepareSymTable( SymbolRec **SymTable, char *symbols )
{
int i = 0, nchars = 1;
memset( SymTable, 0, 256 * sizeof(void*) );
while (*symbols) {
if (*symbols=='\033') {
nchars = *++symbols;
++symbols;
} else {
SymbolRec **RecList = SymTable + *symbols;
SymbolRec *Rec = *RecList;
int count = 0;
while ( Rec ) {
++count;
if ( Rec->More )
++Rec;
else
break;
}
if ( Rec ) {
*RecList = (SymbolRec*)
realloc( *RecList, (count+1)*sizeof(SymbolRec) );
Rec = *RecList + count;
(Rec-1)->More = 1;
} else {
*RecList = (SymbolRec*) malloc( sizeof(SymbolRec) );
Rec = *RecList;
}
strncpy( Rec->Sym, symbols, 4 );
Rec->Len = (char) nchars;
Rec->Index = (char) i;
Rec->More = 0;
symbols += nchars;
++i;
}
}
}
int FindSymbol( SymbolRec **SymTable, const char *str, int *nchars )
{
SymbolRec *Rec = SymTable[ (int)*str ];
while ( Rec ) {
if ( (Rec->Len == 1 && Rec->Sym[0] == str[0])
||
(Rec->Len == 2 && Rec->Sym[0] == str[0] && Rec->Sym[1] == str[1])
||
(Rec->Len == 3 && Rec->Sym[0] == str[0] && Rec->Sym[1] == str[1]
&& Rec->Sym[2] == str[2])
) {
*nchars = Rec->Len;
return Rec->Index;
}
Rec = ( Rec->More ) ? Rec + 1 : NULL;
}
return -1;
}

View File

@ -1,81 +0,0 @@
#pragma once
/*
Universal lexical analiser by hq_software
*/
#ifndef __LEXER_HPP__
#define __LEXER_HPP__
#include "pack.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned char uchar;
typedef enum {
CH_LETTER = 0x01, CH_DIGIT = 0x02, CH_SEPARAT = 0x04,
CH_SYMBOL = 0x08, CH_QUOTE = 0x10,
CH_UNKNOWN= 0x7E, CH_FINAL = 0x7F
} hqCharType;
typedef enum {
TOK_ERROR, TOK_NONE, TOK_FINAL, TOK_INT, TOK_FLOAT, TOK_SYMBOL,
TOK_NAME, TOK_STRING
} hqTokenType;
#pragma pack(push,1)
typedef struct {
char Sym[4];
char Len;
char Index;
char More;
} SymbolRec;
typedef struct {
// input params
const char *SS;
hqCharType *CharTypeTable;
SymbolRec **SymTable;
int NoIntegers;
int cssn; // Comment Start Symbol Number. -1 if none
char *ComEnd; // End of comment
// output params
const char *Name;
size_t NameLen;
double ExtValue;
int IntValue;
hqTokenType PrevTokenType;
hqCharType CharType;
} hqLexer;
#pragma pack(pop)
/* Main "API" */
int Lexer_SetParseString( hqLexer *lexer, const char *str );
hqTokenType Lexer_GetNextToken( hqLexer *lexer );
const char* Lexer_GetCurrentPos( hqLexer *lexer );
/* Misc */
void UpcaseWin1251Str( char *Str );
void InitCharTypeTable( hqCharType *CharTypeTable, int CharTypes );
void TypeTableAddChars( hqCharType *CharTypeTable, char *Symbols,
hqCharType CharType );
void PrepareSymTable( SymbolRec **SymTable, char *symbols );
//int IsEngWin1251RusName( char *Str );
extern char const Win1251UpcaseTbl[];
#ifdef __cplusplus
}
#endif
#endif /* __LEXER_HPP__ */

View File

@ -1,657 +0,0 @@
#include <math.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mparser.h"
//#define MY_DEBUG 1
#ifndef M_E
# define M_E 2.7182818284590452354
#endif
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
const double DblErR = -1.68736462823243E308;
const double DblNiN = -1.68376462823243E308;
char eBrackets [] = "#Brackets not match!";
char eSyntax [] = "#Syntax error!";
char eInternal [] = "#Internal error!";
char eExtraOp [] = "#Extra operation!";
char eInfinity [] = "#Infinity somewhere!";
char eInvArg [] = "#Invalid argument!";
char eUnknFunc [] = "# %s - Unknown function/variable!";
char eExtrnFunc[] = "#External function error!";
char eLogicErr [] = "#Logical expression error!";
char eCalcErr [] = "#Calculation error!";
char eUnexpEnd [] = "#Unexpected end of script!";
char eExpVarRet[] = "#Variable name or return expected!";
char eExpAssign[] = "#Assignment expected!";
char eValSizErr[] = "#Value too big for operation!";
char eInvPrmCnt[] = "#Invalid parameters count for function call!";
static double _neg_(double);
static double _frac_(double);
static double _trunc_(double);
static double _sgn_(double);
static double _neg_(double);
static double _floor_(double);
static double _ceil_(double);
static char* _round_( int paramcnt, double *args, hqStrMap *strparams, double *result );
const Operation BrOp = { OP_OBR };
const Operation NegOp = { OP_FUNC_ONEARG, (void*)&_neg_, 0, NULL };
const char OpPriorities[OP_FUNC_MULTIARG+1] = {
5, 5, 5, 2, 2, 2, 2, 2, -1, -1, 0,
3, 3, 4, 4, 4, 4,
5, 5, 5, 5, 2, 2, 2, 1, 2, 0, 2,
-1, 6, 6 };
char MathSymbols[] =
"\033\002" "<<" ">>" "**" "<>" ">=" "<=" "&&" "||" "/*" ":="
"\033\001" "(+-*/%$^~&|=><?:),;";
char StdSymbols[] = "+-/*^~()<>%$,?:=&|;";
hqCharType MathCharTypeTable[256];
int initializations_performed = 0;
char func_names[] =
"ATAN\000COS\000SIN\000TAN\000ABS\000"
"EXP\000LN\000LOG\000SQRT\000FRAC\000"
"TRUNC\000FLOOR\000CEIL\000ROUND\000ASIN\000"
"ACOS\000SGN\000NEG\000E\000PI\000";
/* Indexes of some functions in func_names[] array */
#define FUNC_ROUND 13
#define FUNC_E 18
#define FUNC_PI 19
static char* CalcToObr( hqMathParser *parser );
static char* Calc( hqMathParser *parser );
static char* MathParser_ParseScript( hqMathParser* parser, double *result );
static char* MathParser_ParseFormula( hqMathParser* parser, double *result );
double (*func_addresses[]) () = {
&atan, &cos, &sin, &tan, &fabs,
&exp, &log, &log10, &sqrt, &_frac_,
&_trunc_, &_floor_, _ceil_, (double(*)(double)) &_round_, &asin,
&acos, &_sgn_, &_neg_, NULL, NULL };
hqStrMap *IntFunctions;
SymbolRec *MathSymTable[256];
char errbuf[256];
// hqMathParser implementation
hqMathParser* MathParser_Create( char *MoreLetters )
{
hqMathParser *parser = calloc( 1, sizeof(hqMathParser) );
if (!initializations_performed) {
// init character tables
InitCharTypeTable( MathCharTypeTable,
CH_LETTER | CH_DIGIT | CH_SEPARAT | CH_QUOTE );
TypeTableAddChars( MathCharTypeTable, StdSymbols, CH_SYMBOL );
if (MoreLetters)
TypeTableAddChars( MathCharTypeTable, MoreLetters, CH_LETTER );
// init function maps
PrepareSymTable( MathSymTable, MathSymbols );
IntFunctions = Strmap_CreateFromChain( sizeof(void*),
(char*)func_names,
func_addresses );
initializations_performed = 1;
}
parser->Lexer.NoIntegers = 1;
parser->Lexer.SymTable = MathSymTable;
parser->Lexer.CharTypeTable = MathCharTypeTable;
parser->Lexer.cssn = 8;
parser->Lexer.ComEnd = "*/";
return parser;
}
void MathParser_Destroy( hqMathParser* parser )
{
free( parser );
}
static char* PrepareFormula( hqMathParser* parser )
{
int BrCnt = 0;
const char *SS = parser->Lexer.SS;
// Brackets Matching
while ( (!parser->script && *SS) || (parser->script && *SS != ';') ) {
if (*SS=='(')
++BrCnt;
else if (*SS==')' && --BrCnt<0)
goto brkerr;
++SS;
}
if (BrCnt != 0)
brkerr: return eBrackets;
parser->OpTop = 0;
parser->ValTop = -1;
parser->OpStack[0].OperType = OP_OBR;
parser->ObrDist = 2;
return NULL;
}
char* MathParser_Parse( hqMathParser* parser, const char *Formula, double *result )
{
if (!Formula || !*Formula) {
*result = 0.0;
return NULL;
}
parser->script = *Formula == '#' && *(Formula+1) == '!'
&& MathCharTypeTable[ (uchar)*(Formula+2) ] == CH_SEPARAT;
if ( parser->script )
Formula += 3;
Lexer_SetParseString( &parser->Lexer, Formula );
return ( parser->script )
?
MathParser_ParseScript( parser, result )
:
MathParser_ParseFormula( parser, result );
}
static char* MathParser_ParseFormula( hqMathParser* parser, double *result )
{
char *ErrorMsg;
hqTokenType ToTi;
if ( (ErrorMsg = PrepareFormula( parser )) != NULL )
return ErrorMsg;
ToTi = Lexer_GetNextToken( &parser->Lexer );
for (;;) {
--parser->ObrDist;
switch (ToTi) {
case TOK_ERROR:
return eSyntax;
case TOK_FINAL:
formulaend: if ( (ErrorMsg = CalcToObr( parser )) != NULL )
return ErrorMsg;
goto getout;
case TOK_FLOAT:
parser->ValStack[++parser->ValTop] = parser->Lexer.ExtValue;
break;
case TOK_SYMBOL:
switch ( parser->Lexer.IntValue ) {
case OP_OBR: // (
parser->OpStack[++parser->OpTop] = BrOp;
parser->ObrDist = 2;
break;
case OP_CBR: // )
if ( (ErrorMsg = CalcToObr( parser )) != NULL )
return ErrorMsg;
break;
case OP_COMMA: { // ,
Operation *pOp;
if ( (ErrorMsg = CalcToObr( parser )) != NULL )
return ErrorMsg;
if ( (pOp = &parser->OpStack[parser->OpTop])->OperType
== OP_FUNC_MULTIARG ) {
parser->OpStack[++parser->OpTop] = BrOp;
parser->ObrDist = 2;
} else
return eSyntax;
break;
}
default: {
Operation Op;
Op.OperType = (OperType_t) parser->Lexer.IntValue;
switch (Op.OperType) {
case OP_FORMULAEND:
if (parser->script)
goto formulaend;
else
return eSyntax;
case OP_ADD:
if (parser->ObrDist >= 1)
goto next_tok;
break;
case OP_SUB:
if (parser->ObrDist >= 1) {
parser->OpStack[++parser->OpTop] = NegOp;
goto next_tok;
}
break;
case OP_LOGIC:
case OP_LOGIC_SEP:
parser->ObrDist = 2;
default:
break;
}
while ( OpPriorities[ Op.OperType ]
<=
OpPriorities[ parser->OpStack[parser->OpTop].OperType ] ) {
if ( (ErrorMsg = Calc( parser )) != NULL )
return ErrorMsg;
}
parser->OpStack[++parser->OpTop] = Op;
break;
}
}
break;
case TOK_NAME: {
Operation Op;
double *value, dblval;
void **func;
int funcnum, /*i,*/ namelen = parser->Lexer.NameLen;
// const char *SS = parser->Lexer.Name;
// for (i = namelen; i>0; --i)
// *SS++ = Win1251UpcaseTbl[ (int) (uchar) *SS ];
funcnum = StrMap_LenIndexOf( IntFunctions,
parser->Lexer.Name,
parser->Lexer.NameLen,
(void**) &func );
if ( funcnum >= 0 ) {
Op.Func = *func;
switch ( funcnum ) {
case FUNC_E:
parser->ValStack[++parser->ValTop] = M_E;
break;
case FUNC_PI:
parser->ValStack[++parser->ValTop] = M_PI;
break;
case FUNC_ROUND:
Op.OperType = OP_FUNC_MULTIARG;
Op.PrevValTop = parser->ValTop;
Op.StrParams = NULL;
parser->OpStack[++parser->OpTop] = Op;
break;
default:// Internal function
Op.OperType = OP_FUNC_ONEARG;
parser->OpStack[++parser->OpTop] = Op;
}
} else if (parser->Parameters
&&
StrMap_LenIndexOf( parser->Parameters,
parser->Lexer.Name,
parser->Lexer.NameLen,
(void**) &value ) >= 0
) {
if (*value==DblErR) {
return eInternal;
} else
parser->ValStack[++parser->ValTop] = *value;
} else if (parser->ExtFunctions
&&
StrMap_LenIndexOf( parser->ExtFunctions,
parser->Lexer.Name,
parser->Lexer.NameLen,
(void**) &func ) >= 0
) {
Op.Func = *func;
Op.OperType = OP_FUNC_MULTIARG;
Op.PrevValTop = parser->ValTop;
Op.StrParams = NULL;
parser->OpStack[++parser->OpTop] = Op;
} else if (parser->VarParams
&&
StrMap_LenIndexOf( parser->VarParams,
parser->Lexer.Name,
parser->Lexer.NameLen,
(void**) &value ) >= 0
) {
if (*value==DblErR) {
return eInternal;
} else
parser->ValStack[++parser->ValTop] = *value;
} else if (parser->MoreParams
&&
(*parser->MoreParams)( parser->Lexer.Name,
parser->Lexer.NameLen,
&dblval,
parser->ParamFuncParam )
) {
parser->ValStack[++parser->ValTop] = dblval;
} else {
char buf[256];
strncpy( buf, parser->Lexer.Name, parser->Lexer.NameLen );
buf[ parser->Lexer.NameLen ] = '\0';
sprintf( errbuf, eUnknFunc, buf );
return errbuf;
}
break;
}
case TOK_STRING: {
Operation *pOp;
if (parser->OpTop < 1)
return eSyntax;
if ( (pOp = &parser->OpStack[parser->OpTop-1])->OperType
== OP_FUNC_MULTIARG ) {
if (!pOp->StrParams)
pOp->StrParams = Strmap_Create( 0, 0 );
StrMap_AddStrLen( pOp->StrParams,
parser->Lexer.Name,
parser->Lexer.NameLen, NULL );
parser->ValStack[++parser->ValTop] = DblNiN;
} else
return eSyntax;
break;
}
default:
return eSyntax;
}
next_tok:
ToTi = Lexer_GetNextToken( &parser->Lexer );
} // forever
getout:
if (parser->OpTop != -1 || parser->ValTop != 0)
return eInternal;
*result = parser->ValStack[0];
return NULL;
}
static char* MathParser_ParseScript( hqMathParser* parser, double *result )
{
char *ErrorMsg = NULL;
hqTokenType ToTi;
int expectvar = 1, was_return = 0;
const char *varname = NULL;
int varnamelen = 0;
parser->VarParams = Strmap_Create( sizeof(double), 0 );
ToTi = Lexer_GetNextToken( &parser->Lexer );
for (;;) {
switch (ToTi) {
case TOK_FINAL:
ErrorMsg = eUnexpEnd;
goto getout;
case TOK_NAME: {
if (!expectvar) {
ErrorMsg = eExpVarRet;
goto getout;
} else {
// int i;
// const char *SS = parser->Lexer.Name;
varnamelen = parser->Lexer.NameLen;
// for (i = varnamelen; i>0; --i)
// *SS++ = Win1251UpcaseTbl[ (int) (uchar) *SS ];
}
varname = parser->Lexer.Name;
was_return = strncmp( varname, "RETURN", varnamelen ) == 0;
if ( was_return ) {
ErrorMsg = MathParser_ParseFormula( parser, result );
goto getout;
}
expectvar = 0;
break;
}
case TOK_SYMBOL: {
double *value;
if ( parser->Lexer.IntValue != OP_ASSIGN || expectvar ) {
ErrorMsg = eExpAssign;
goto getout;
}
ErrorMsg = MathParser_ParseFormula( parser, result );
if (ErrorMsg)
goto getout;
if ( StrMap_LenIndexOf( parser->VarParams,
varname, varnamelen,
(void**) &value ) >= 0 )
*value = *result;
else
StrMap_AddStrLen( parser->VarParams, varname, varnamelen,
result );
expectvar = 1;
break;
}
default:
ErrorMsg = eSyntax;
goto getout;
}
ToTi = Lexer_GetNextToken( &parser->Lexer );
} // forever
getout:
StrMap_Destroy( parser->VarParams );
parser->VarParams = NULL;
return ErrorMsg;
}
static char* Calc( hqMathParser *parser )
{
double Res, ValR;
Operation Op = parser->OpStack[parser->OpTop--];
// multi-argument external or internal fucntion
if ( Op.OperType == OP_FUNC_MULTIARG ) {
int paramcnt = parser->ValTop - Op.PrevValTop;
char *ErrorMsg;
#ifdef MY_DEBUG
printf( "ValTop = %d, OpTop = %d, PrevValTop = %d\n",
parser->ValTop, parser->OpTop, Op.PrevValTop );
#endif
parser->ValTop = Op.PrevValTop;
ErrorMsg = (*(MultiArgFunc)Op.Func)( paramcnt,
&parser->ValStack[parser->ValTop+1],
Op.StrParams, &Res );
if (ErrorMsg)
return ErrorMsg;
if (Op.StrParams)
StrMap_Destroy( Op.StrParams );
parser->ValStack[++parser->ValTop] = Res;
#ifdef MY_DEBUG
printf("ValTop = %d, OpTop = %d\n", parser->ValTop, parser->OpTop );
#endif
return NULL;
}
if (Op.OperType==OP_LOGIC)
return NULL;
// get right arg
if (parser->ValTop<0)
return eExtraOp;
ValR = parser->ValStack[parser->ValTop--];
// one arg operations
if (Op.OperType==OP_NOT) {
if (ValR >= INT_MIN && ValR <= INT_MAX)
Res = ~((int) ValR);
else
return eValSizErr;
} else if (Op.OperType==OP_FUNC_ONEARG) {
Res = (*(OneArgFunc)Op.Func)( ValR );
} else {
// get left arg
double ValL;
if (parser->ValTop<0)
return eExtraOp;
ValL = parser->ValStack[parser->ValTop--];
switch (Op.OperType) {
// Binary
case OP_SHL:
if (ValL >= INT_MIN && ValL <= INT_MAX && ValR >= INT_MIN && ValR <= INT_MAX)
Res = (int) ValL << (int) ValR;
else
return eValSizErr;
break;
case OP_SHR:
if (ValL >= INT_MIN && ValL <= INT_MAX && ValR >= INT_MIN && ValR <= INT_MAX)
Res = (int) ValL >> (int) ValR;
else
return eValSizErr;
break;
case OP_POW:
Res = pow( ValL, ValR ); break;
// Logical
case OP_LOGIC_NEQ:
Res = ValL != ValR; break;
case OP_LOGIC_GEQ:
Res = ValL >= ValR; break;
case OP_LOGIC_LEQ:
Res = ValL <= ValR; break;
case OP_LOGIC_AND:
Res = ValL && ValR; break;
case OP_LOGIC_OR:
Res = ValL || ValR; break;
// Arithmetic
case OP_ADD:
Res = ValL + ValR; break;
case OP_SUB:
Res = ValL - ValR; break;
case OP_MUL:
Res = ValL * ValR; break;
case OP_DIV:
if (ValR == 0.0)
return eInfinity;
Res = ValL / ValR;
break;
case OP_MOD:
Res = fmod(ValL, ValR); break;
case OP_UNK:
if (ValL<=0)
Res = 0.0;
else if (ValR==0.0)
return eInfinity;
else
Res = ceil(ValL / ValR);
break;
// Bitwise
case OP_XOR:
if (ValL >= INT_MIN && ValL <= INT_MAX && ValR >= INT_MIN && ValR <= INT_MAX)
Res = (int) ValL ^ (int) ValR;
else
return eValSizErr;
break;
case OP_AND:
if (ValL >= INT_MIN && ValL <= INT_MAX && ValR >= INT_MIN && ValR <= INT_MAX)
Res = (int) ValL & (int) ValR;
else
return eValSizErr;
break;
case OP_OR:
if (ValL >= INT_MIN && ValL <= INT_MAX && ValR >= INT_MIN && ValR <= INT_MAX)
Res = (int) ValL | (int) ValR;
else
return eValSizErr;
break;
// Logical
case OP_EQU:
Res = ValL == ValR; break;
case OP_GREATER:
Res = ValL > ValR; break;
case OP_LESS:
Res = ValL < ValR; break;
case OP_LOGIC_SEP: {
// needs three arguments
double ValLL;
if (parser->OpTop < 0
|| parser->OpStack[parser->OpTop--].OperType != OP_LOGIC)
return eLogicErr;
ValLL = parser->ValStack[ parser->ValTop-- ];
Res = ValLL ? ValL : ValR;
break;
}
default:
return eInternal;
}
}
parser->ValStack[++parser->ValTop] = Res;
return NULL;
}
static char* CalcToObr( hqMathParser *parser )
{
while ( parser->OpStack[parser->OpTop].OperType != OP_OBR ) {
char *ErrorMsg;
if ( (ErrorMsg = Calc( parser )) != NULL )
return ErrorMsg;
}
--parser->OpTop;
return NULL;
}
/* misc functions */
static double _frac_( double x )
{
double y;
return modf(x, &y);
}
static double _trunc_( double x )
{
return (x >= 0.0) ? floor(x) : ceil(x);
}
static double _sgn_( double x )
{
return (x > 0) ? 1 : (x < 0) ? -1 : 0;
}
static double _neg_( double x )
{
return -x;
}
static double _floor_( double x )
{
return floor(x);
}
static double _ceil_( double x )
{
return ceil(x);
}
/* "Advanced" round function; second argument - sharpness */
static char* _round_( int paramcnt, double *args, hqStrMap *strparams, double *result )
{
int i, sharpness;
double x, coef;
if (paramcnt == 1)
sharpness = 0;
else if (paramcnt == 2)
sharpness = (int) args[1];
else
return eInvPrmCnt;
x = args[0];
if (sharpness < 0) {
coef = 0.1;
sharpness = -sharpness;
} else
coef = 10;
for (i = 0; i < sharpness; i++)
x *= coef;
x = (x + ( (x >= 0) ? 0.5 : -0.5 ) );
if (x >= 0.0)
x = floor(x);
else
x = ceil(x);
for (i = 0; i < sharpness; i++)
x /= coef;
*result = x;
return NULL;
}

View File

@ -1,82 +0,0 @@
#pragma once
/*
Math parser for CCalc library.
*/
#include "strmap.h"
#include "lexer.h"
#include "pack.h"
//#define RUSSIAN 1
#ifdef __cplusplus
extern "C" {
#endif
#define MAX_STACK_SIZE 32
extern const double DblErR;
extern const double DblNiN;
typedef enum {
// Binary
OP_SHL, OP_SHR, OP_POW,
OP_LOGIC_NEQ, OP_LOGIC_GEQ, OP_LOGIC_LEQ,
OP_LOGIC_AND, OP_LOGIC_OR, // Logical
OP_COMSTART, OP_ASSIGN, // For internal needs
OP_OBR, // Special
OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_UNK, // Arithmetic
OP_XOR, OP_NOT, OP_AND, OP_OR, // Bitwise
OP_EQU, OP_GREATER, OP_LESS,
OP_LOGIC, OP_LOGIC_SEP, OP_CBR, OP_COMMA, // Logical
OP_FORMULAEND, // For script
OP_FUNC_ONEARG, OP_FUNC_MULTIARG // Special
} OperType_t;
typedef struct {
char *str;
double value;
} Parameter;
typedef double (*OneArgFunc) ( double arg );
typedef char* (*MultiArgFunc) ( int paramcnt, double *args,
hqStrMap *strparams, double *result );
typedef int (*PrmSrchFunc) ( const char *str, int len, double *value,
void *param );
#pragma pack(push,1)
typedef struct {
OperType_t OperType;
void *Func;
char PrevValTop;
hqStrMap *StrParams;
} Operation;
typedef struct {
/* public */
hqStrMap *Parameters; // List of numeric veriables
hqStrMap *ExtFunctions; // List of multi-argument external functions
PrmSrchFunc MoreParams; // Function for calculating unhandled parameters
void *ParamFuncParam; // Parameter given to this function
/* private */
Operation OpStack[MAX_STACK_SIZE];
double ValStack[MAX_STACK_SIZE];
int OpTop, ValTop;
int ObrDist;
hqLexer Lexer;
int script;
hqStrMap *VarParams;
} hqMathParser;
#pragma pack(pop)
/* API */
hqMathParser* MathParser_Create( char *MoreLetters );
void MathParser_Destroy( hqMathParser* parser );
char* MathParser_Parse( hqMathParser* parser, const char *Formula, double *result );
#ifdef __cplusplus
}
#endif

View File

@ -1,23 +0,0 @@
/* Definitions for packing structures */
#ifndef __PACK_H__
#define __PACK_H__
#if defined(__BORLANDC__) && (__BORLANDC <= 0x520)
# define PACK_START #pragma option -a1
#elif (defined(__GNUC__) && (__GNUC__ <= 2) && (__GNUC_MINOR__ < 95)) \
|| (defined(__WATCOMC__) && (__WATCOMC__ < 1100))
# define PACK_START #pragma pack(1)
#else
# define PACK_START #pragma pack(push,1)
#endif
#if defined(__BORLANDC__) && (__BORLANDC <= 0x520)
# define PACK_STOP #pragma option -a.
#elif (defined(__GNUC__) && (__GNUC__ <= 2) && (__GNUC_MINOR__ < 95)) \
|| (defined(__WATCOMC__) && (__WATCOMC__ < 1100))
# define PACK_STOP #pragma pack()
#else
# define PACK_STOP #pragma pack(pop)
#endif
#endif /* __PACK_H__ */

View File

@ -1,129 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include "strmap.h"
hqStrMap* create_instance( int extrabytes, int dup )
{
hqStrMap* strmap = calloc( 1, sizeof(hqStrMap) );
strmap->FDoDuplicate = dup;
strmap->FExtraLen = extrabytes;
strmap->FRecordLen = sizeof(char*) + sizeof(int) + extrabytes;
strmap->FList = NULL;
return strmap;
}
hqStrMap* Strmap_Create( int extrabytes, int dup )
{
return create_instance( extrabytes, dup );
}
void Strmap_FillFromChain( hqStrMap* strmap, char *strchain, void *data )
{
while ( *strchain ) {
size_t len = strlen( strchain );
StrMap_AddStrLen( strmap, strchain, len, data );
strchain += len+1;
data = (char*)data + strmap->FExtraLen;
}
}
hqStrMap* Strmap_CreateFromChain( int extrabytes, char *strchain, void *data )
{
hqStrMap* strmap = create_instance( extrabytes, 0 );
Strmap_FillFromChain( strmap, strchain, data );
StrMap_ShrinkMem( strmap );
return strmap;
}
void StrMap_Destroy( hqStrMap* strmap )
{
if ( strmap->FDoDuplicate )
StrMap_TrimClear( strmap, 0 );
if ( strmap->FList )
free( strmap->FList );
free(strmap);
}
void StrMap_AddString( hqStrMap* strmap, const char *str, void *data )
{
StrMap_AddStrLen( strmap, str, strlen(str), data );
}
void StrMap_AddStrLen( hqStrMap* strmap, const char *str, size_t len, void *data )
{
const char *Rec;
if ( strmap->FCount >= strmap->FCapacity ) {
int delta = (strmap->FCapacity > 64) ? strmap->FCapacity / 4 : 16;
StrMap_SetCapacity( strmap, strmap->FCapacity + delta );
}
Rec = strmap->FList + strmap->FCount * strmap->FRecordLen;
*(const char**)Rec = str;
*(int*)(Rec + sizeof(char*)) = len;
if (data) {
void *recdata = (void*)(Rec + sizeof(char*) + sizeof(int));
memcpy( recdata, data, strmap->FExtraLen );
}
++ strmap->FCount;
}
void StrMap_ShrinkMem( hqStrMap* strmap )
{
StrMap_SetCapacity( strmap, strmap->FCount );
}
void StrMap_Trim( hqStrMap* strmap, int NewCount )
{
strmap->FCount = NewCount;
}
void StrMap_TrimClear( hqStrMap* strmap, int NewCount )
{
int i;
char *Rec = strmap->FList + NewCount * strmap->FRecordLen;
for (i=NewCount; i < strmap->FCount; i++) {
free( *(char**)Rec );
Rec += strmap->FRecordLen;
}
strmap->FCount = NewCount;
}
void StrMap_SetCapacity( hqStrMap* strmap, int NewCapacity )
{
strmap->FCapacity = NewCapacity;
if ( strmap->FCount > strmap->FCapacity )
strmap->FCount = strmap->FCapacity;
strmap->FList = (char*) realloc( strmap->FList,
strmap->FCapacity * strmap->FRecordLen );
}
int StrMap_IndexOf( hqStrMap* strmap, const char *str, void **data )
{
return StrMap_LenIndexOf( strmap, str, strlen(str), data );
}
int StrMap_LenIndexOf( hqStrMap* strmap, const char *str, size_t len, void **data )
{
int i;
char *Rec = strmap->FList;
for (i=0; i<strmap->FCount; i++) {
int recLen = *(int*)(Rec + sizeof(char*));
if (recLen==len && strnicmp( str, *(char**)Rec, recLen )==0 ) {
*data = (Rec + sizeof(char*) + sizeof(int));
return i;
}
Rec += strmap->FRecordLen;
}
*data = NULL;
return -1;
}
char* StrMap_GetString( hqStrMap* strmap, int index, int *len, void **data )
{
char *Rec = strmap->FList + index * strmap->FRecordLen;
*len = *(int*)(Rec + sizeof(char*));
if (data!=NULL && strmap->FExtraLen>0)
*data = (Rec + sizeof(char*) + sizeof(int));
return *(char**)Rec;
}

View File

@ -1,39 +0,0 @@
#pragma once
#include "pack.h"
#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(push,1)
typedef struct {
int FCount, FCapacity;
int FExtraLen, FRecordLen;
int FDoDuplicate;
char *FList;
} hqStrMap;
#pragma pack(pop)
/* API */
hqStrMap* Strmap_Create( int extrabytes, int dup );
hqStrMap* Strmap_CreateFromChain( int extrabytes, char *strchain, void *data );
void StrMap_Destroy( hqStrMap* strmap );
void StrMap_AddString( hqStrMap* strmap, const char *str, void *data );
void StrMap_AddStrLen( hqStrMap* strmap, const char *str, size_t len, void *data );
void StrMap_ShrinkMem( hqStrMap* strmap );
void StrMap_Trim( hqStrMap* strmap, int NewCount );
void StrMap_TrimClear( hqStrMap* strmap, int NewCount );
void StrMap_SetCapacity( hqStrMap* strmap, int NewCapacity );
int StrMap_IndexOf( hqStrMap* strmap, const char *str, void **data );
int StrMap_LenIndexOf( hqStrMap* strmap, const char *str, size_t len, void **data );
char* StrMap_GetString( hqStrMap* strmap, int index, int *len, void **data );
void Strmap_FillFromChain( hqStrMap* strmap, char *strchain, void *data );
#ifdef __cplusplus
}
#endif

View File

@ -1,6 +0,0 @@
#include <windows.h>
extern int WINAPI dll_entry (HANDLE h, DWORD reason, void *ptr)
{
return 1;
}