Adding support for RegExp in Substitute strings when RegExpSubstitute=1 is set.

This commit is contained in:
JamesAC 2011-07-29 11:49:46 +00:00
parent 45007fc8d8
commit d7dedcfc75
6 changed files with 272 additions and 27 deletions

View File

@ -95,7 +95,7 @@
<ClCompile> <ClCompile>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>lua/include;lua/lua;lua/tolua++;lua/glue;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>lua/include;lua/lua;lua/tolua++;lua/glue;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBRARY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;HAVE_CONFIG_H;SUPPORT_UTF8;LIBRARY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
@ -138,7 +138,7 @@
<ClCompile> <ClCompile>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>lua/include;lua/lua;lua/tolua++;lua/glue;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>lua/include;lua/lua;lua/tolua++;lua/glue;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBRARY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;HAVE_CONFIG_H;SUPPORT_UTF8;LIBRARY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<RuntimeTypeInfo>true</RuntimeTypeInfo> <RuntimeTypeInfo>true</RuntimeTypeInfo>
@ -182,7 +182,7 @@
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>lua/include;lua/lua;lua/tolua++;lua/glue;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>lua/include;lua/lua;lua/tolua++;lua/glue;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBRARY_EXPORTS;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBRARY_EXPORTS;HAVE_CONFIG_H;SUPPORT_UTF8;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
@ -232,7 +232,7 @@
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>Default</InlineFunctionExpansion> <InlineFunctionExpansion>Default</InlineFunctionExpansion>
<AdditionalIncludeDirectories>lua/include;lua/lua;lua/tolua++;lua/glue;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>lua/include;lua/lua;lua/tolua++;lua/glue;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBRARY_EXPORTS;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBRARY_EXPORTS;HAVE_CONFIG_H;SUPPORT_UTF8;_SECURE_SCL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling> <StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
@ -611,6 +611,26 @@
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization> <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Use</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Use</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="pcre-8.10\pcre_chartables.c" />
<ClCompile Include="pcre-8.10\pcre_compile.c" />
<ClCompile Include="pcre-8.10\pcre_config.c" />
<ClCompile Include="pcre-8.10\pcre_dfa_exec.c" />
<ClCompile Include="pcre-8.10\pcre_exec.c" />
<ClCompile Include="pcre-8.10\pcre_fullinfo.c" />
<ClCompile Include="pcre-8.10\pcre_get.c" />
<ClCompile Include="pcre-8.10\pcre_globals.c" />
<ClCompile Include="pcre-8.10\pcre_info.c" />
<ClCompile Include="pcre-8.10\pcre_maketables.c" />
<ClCompile Include="pcre-8.10\pcre_newline.c" />
<ClCompile Include="pcre-8.10\pcre_ord2utf8.c" />
<ClCompile Include="pcre-8.10\pcre_refcount.c" />
<ClCompile Include="pcre-8.10\pcre_study.c" />
<ClCompile Include="pcre-8.10\pcre_tables.c" />
<ClCompile Include="pcre-8.10\pcre_try_flipped.c" />
<ClCompile Include="pcre-8.10\pcre_ucd.c" />
<ClCompile Include="pcre-8.10\pcre_valid_utf8.c" />
<ClCompile Include="pcre-8.10\pcre_version.c" />
<ClCompile Include="pcre-8.10\pcre_xclass.c" />
<ClCompile Include="Rainmeter.cpp"> <ClCompile Include="Rainmeter.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization> <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
@ -855,6 +875,10 @@
<ClInclude Include="MeterRoundLine.h" /> <ClInclude Include="MeterRoundLine.h" />
<ClInclude Include="MeterString.h" /> <ClInclude Include="MeterString.h" />
<ClInclude Include="MeterWindow.h" /> <ClInclude Include="MeterWindow.h" />
<ClInclude Include="pcre-8.10\config.h" />
<ClInclude Include="pcre-8.10\pcre.h" />
<ClInclude Include="pcre-8.10\pcre_internal.h" />
<ClInclude Include="pcre-8.10\ucp.h" />
<ClInclude Include="Rainmeter.h" /> <ClInclude Include="Rainmeter.h" />
<ClInclude Include="RainmeterQuery.h" /> <ClInclude Include="RainmeterQuery.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />

View File

@ -31,6 +31,9 @@
<Filter Include="Lua\Lua"> <Filter Include="Lua\Lua">
<UniqueIdentifier>{c8550e7b-009b-4e12-a55a-ed458d05bdad}</UniqueIdentifier> <UniqueIdentifier>{c8550e7b-009b-4e12-a55a-ed458d05bdad}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="pcre">
<UniqueIdentifier>{5866a61e-ec27-469c-a8f0-2a45ce141f60}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="AboutDialog.cpp"> <ClCompile Include="AboutDialog.cpp">
@ -294,6 +297,66 @@
<ClCompile Include="lua\lua\print.c"> <ClCompile Include="lua\lua\print.c">
<Filter>Lua\Lua</Filter> <Filter>Lua\Lua</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="pcre-8.10\pcre_chartables.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_compile.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_config.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_dfa_exec.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_exec.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_fullinfo.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_get.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_globals.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_info.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_maketables.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_newline.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_ord2utf8.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_refcount.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_study.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_tables.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_try_flipped.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_ucd.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_valid_utf8.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_version.c">
<Filter>pcre</Filter>
</ClCompile>
<ClCompile Include="pcre-8.10\pcre_xclass.c">
<Filter>pcre</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="Library.rc"> <ResourceCompile Include="Library.rc">
@ -526,6 +589,18 @@
<ClInclude Include="lua\lua\lzio.h"> <ClInclude Include="lua\lua\lzio.h">
<Filter>Lua\Lua</Filter> <Filter>Lua\Lua</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="pcre-8.10\config.h">
<Filter>pcre</Filter>
</ClInclude>
<ClInclude Include="pcre-8.10\pcre.h">
<Filter>pcre</Filter>
</ClInclude>
<ClInclude Include="pcre-8.10\pcre_internal.h">
<Filter>pcre</Filter>
</ClInclude>
<ClInclude Include="pcre-8.10\ucp.h">
<Filter>pcre</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Res\tray.ico"> <None Include="Res\tray.ico">

View File

@ -500,6 +500,46 @@ std::wstring ConvertToWide(LPCSTR str)
return szWide; return szWide;
} }
std::string ConvertToUTF8(LPCWSTR str)
{
std::string szAscii;
if (str && *str)
{
int strLen = (int)wcslen(str) + 1;
int bufLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL, NULL);
if (bufLen > 0)
{
char* tmpSz = new char[bufLen];
tmpSz[0] = 0;
WideCharToMultiByte(CP_UTF8, 0, str, strLen, tmpSz, bufLen, NULL, NULL);
szAscii = tmpSz;
delete [] tmpSz;
}
}
return szAscii;
}
std::wstring ConvertUTF8ToWide(LPCSTR str)
{
std::wstring szWide;
if (str && *str)
{
int strLen = (int)strlen(str) + 1;
int bufLen = MultiByteToWideChar(CP_UTF8, 0, str, strLen, NULL, 0);
if (bufLen > 0)
{
WCHAR* wideSz = new WCHAR[bufLen];
wideSz[0] = 0;
MultiByteToWideChar(CP_UTF8, 0, str, strLen, wideSz, bufLen);
szWide = wideSz;
delete [] wideSz;
}
}
return szWide;
}
BOOL LSLog(int nLevel, LPCTSTR pszModule, LPCTSTR pszMessage) BOOL LSLog(int nLevel, LPCTSTR pszModule, LPCTSTR pszMessage)
{ {
CRainmeter::LOG_INFO logInfo; CRainmeter::LOG_INFO logInfo;

View File

@ -56,6 +56,8 @@ void ResetLoggingFlag();
std::string ConvertToAscii(LPCTSTR str); std::string ConvertToAscii(LPCTSTR str);
std::wstring ConvertToWide(LPCSTR str); std::wstring ConvertToWide(LPCSTR str);
std::string ConvertToUTF8(LPCWSTR str);
std::wstring ConvertUTF8ToWide(LPCSTR str);
HINSTANCE LSExecuteAsAdmin(HWND Owner, LPCTSTR szCommand, int nShowCmd); HINSTANCE LSExecuteAsAdmin(HWND Owner, LPCTSTR szCommand, int nShowCmd);
HINSTANCE ExecuteCommand(HWND Owner, LPCTSTR szCommand, int nShowCmd, LPCTSTR szVerb); HINSTANCE ExecuteCommand(HWND Owner, LPCTSTR szCommand, int nShowCmd, LPCTSTR szVerb);

View File

@ -35,6 +35,10 @@
#include "Rainmeter.h" #include "Rainmeter.h"
#include "Error.h" #include "Error.h"
#include "Litestep.h" #include "Litestep.h"
#include "pcre-8.10/config.h"
#include "pcre-8.10/pcre.h"
#define OVECCOUNT 300 // Should be a multiple of 3
enum AUTOSCALE_INDEX enum AUTOSCALE_INDEX
{ {
@ -74,6 +78,7 @@ CMeasure::CMeasure(CMeterWindow* meterWindow, const WCHAR* name) : m_MeterWindow
m_MinValue(), m_MinValue(),
m_MaxValue(1.0), m_MaxValue(1.0),
m_Value(), m_Value(),
m_RegExpSubstitute(false),
m_MedianPos(), m_MedianPos(),
m_AveragePos(), m_AveragePos(),
m_AverageSize(), m_AverageSize(),
@ -165,6 +170,7 @@ void CMeasure::ReadConfig(CConfigParser& parser, const WCHAR* section)
m_DynamicVariables = 0!=parser.ReadInt(section, L"DynamicVariables", 0); m_DynamicVariables = 0!=parser.ReadInt(section, L"DynamicVariables", 0);
m_RegExpSubstitute = 0!=parser.ReadInt(section, L"RegExpSubstitute", 0);
std::wstring subs = parser.ReadString(section, L"Substitute", L""); std::wstring subs = parser.ReadString(section, L"Substitute", L"");
if (!subs.empty() && if (!subs.empty() &&
(subs[0] != L'\"' || subs[subs.length() - 1] != L'\'') && (subs[0] != L'\"' || subs[subs.length() - 1] != L'\'') &&
@ -183,6 +189,29 @@ void CMeasure::ReadConfig(CConfigParser& parser, const WCHAR* section)
InitializeGroup(group); InitializeGroup(group);
} }
/*
** MakePlainSubstitute
**
** Substitues text using a straight find and replace method
*/
bool CMeasure::MakePlainSubstitute(std::wstring& str, size_t index)
{
size_t start = 0;
size_t pos = std::wstring::npos;
do
{
pos = str.find(m_Substitute[index].first, start);
if (pos != std::wstring::npos)
{
str.replace(pos, m_Substitute[index].first.length(), m_Substitute[index].second);
start = pos + m_Substitute[index].second.length();
}
} while (pos != std::wstring::npos);
return true;
}
/* /*
** CheckSubstitute ** CheckSubstitute
** **
@ -194,31 +223,105 @@ const WCHAR* CMeasure::CheckSubstitute(const WCHAR* buffer)
if (!m_Substitute.empty()) if (!m_Substitute.empty())
{ {
str = buffer; if (!m_RegExpSubstitute) // Plain Substitutions only
for (size_t i = 0, isize = m_Substitute.size(); i < isize; i += 2)
{ {
if (str.empty() && m_Substitute[i].empty()) str = buffer;
{
// Empty result and empty substitute -> use second
str = m_Substitute[i + 1];
}
else if (!m_Substitute[i].empty())
{
size_t start = 0;
size_t pos = std::wstring::npos;
do for (size_t i = 0, isize = m_Substitute.size(); i < isize; i++)
{
if (str.empty() && m_Substitute[i].first.empty())
{ {
pos = str.find(m_Substitute[i], start); // Empty result and empty substitute -> use second
if (pos != std::wstring::npos) str = m_Substitute[i].second;
{ }
str.replace(pos, m_Substitute[i].length(), m_Substitute[i + 1]); else if (!m_Substitute[i].first.empty())
start = pos + m_Substitute[i + 1].length(); {
} MakePlainSubstitute(str, i);
} while (pos != std::wstring::npos); }
} }
} }
else // Contains a RegEx
{
std::string utf8str = ConvertToUTF8(buffer);
for (size_t i = 0, isize = m_Substitute.size() ; i < isize ; i++)
{
pcre* re;
const char* error;
int erroffset;
int ovector[OVECCOUNT];
int rc;
int flags = PCRE_UTF8;
int offset = 0;
re = pcre_compile(
ConvertToUTF8(m_Substitute[i].first.c_str()).c_str(), // the pattern
flags, // default options
&error, // for error message
&erroffset, // for error offset
NULL); // use default character tables
if (re == NULL)
{
MakePlainSubstitute(str, i);
Log(LOG_NOTICE, ConvertToWide(error).c_str());
}
else
{
do
{
rc = pcre_exec(
re, // the compiled pattern
NULL, // no extra data - we didn't study the pattern
utf8str.c_str(), // the subject string
utf8str.length(), // the length of the subject
offset, // start at offset 0 in the subject
0, // default options
ovector, // output vector for substring information
OVECCOUNT); // number of elements in the output vector
if (rc <= 0)
{
break;
}
else
{
std::string result = ConvertToUTF8(m_Substitute[i].second.c_str());
if (rc > 1)
{
for (int j = rc - 1 ; j > 0 ; j--)
{
size_t new_start = ovector[2*j];
size_t in_length = ovector[2*j+1] - ovector[2*j];
char tmpName[64];
_snprintf_s(tmpName, _TRUNCATE, "\\%i", j);
size_t cut_length = strlen(tmpName);
size_t pos = result.find(tmpName);
while (pos != std::string::npos)
{
result.replace(pos, cut_length, utf8str, new_start, in_length);
pos = result.find(tmpName, pos + in_length);
}
}
}
size_t start = ovector[0];
size_t length = ovector[1] - ovector[0];
utf8str.replace(start, length, result);
offset = start + result.length();
}
} while (true);
// Release memory used for the compiled pattern
pcre_free(re);
}
}
str = ConvertUTF8ToWide(utf8str.c_str());
}
return str.c_str(); return str.c_str();
} }
@ -247,8 +350,7 @@ bool CMeasure::ParseSubstitute(std::wstring buffer)
if (word1 != word2) if (word1 != word2)
{ {
m_Substitute.push_back(word1); m_Substitute.push_back(std::pair<std::wstring, std::wstring>(word1, word2));
m_Substitute.push_back(word2);
} }
sep = ExtractWord(buffer); sep = ExtractWord(buffer);

View File

@ -92,6 +92,7 @@ protected:
bool ParseSubstitute(std::wstring buffer); bool ParseSubstitute(std::wstring buffer);
std::wstring ExtractWord(std::wstring& buffer); std::wstring ExtractWord(std::wstring& buffer);
const WCHAR* CheckSubstitute(const WCHAR* buffer); const WCHAR* CheckSubstitute(const WCHAR* buffer);
bool MakePlainSubstitute(std::wstring& str, size_t index);
bool m_DynamicVariables; // If true, the measure contains dynamic variables bool m_DynamicVariables; // If true, the measure contains dynamic variables
bool m_Invert; // If true, the value should be inverted bool m_Invert; // If true, the value should be inverted
@ -102,7 +103,8 @@ protected:
const std::wstring m_Name; // Name of this Measure const std::wstring m_Name; // Name of this Measure
const std::string m_ANSIName; // Name of this Measure in ANSI const std::string m_ANSIName; // Name of this Measure in ANSI
std::vector<std::wstring> m_Substitute; // Vec of substitute strings std::vector< std::pair<std::wstring, std::wstring> > m_Substitute; // Vec of substitute strings
bool m_RegExpSubstitute;
std::vector<double> m_MedianMaxValues; // The values for the median filtering std::vector<double> m_MedianMaxValues; // The values for the median filtering
std::vector<double> m_MedianMinValues; // The values for the median filtering std::vector<double> m_MedianMinValues; // The values for the median filtering